Examples
Common tasks, each in curl, JavaScript, PHP and Python. Put your key in WEBKIO_API_KEY (create one in the console). Every endpoint and field is in the API reference; for events pushed to you, see Webhooks.
Check your key
The account a key belongs to. A quick way to see a key works.
In the API reference: GET /v1/me
curl "https://api.webkio.com/v1/me" \
-H "Authorization: Bearer $WEBKIO_API_KEY"
const res = await fetch('https://api.webkio.com/v1/me', {
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
},
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/me');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.get(
'https://api.webkio.com/v1/me',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
)
data = res.json()['data']
List your sites
Every list is cursor-paginated: pass meta.next_cursor as cursor until meta.has_more is false. A site's id is the project_id the other calls take.
In the API reference: GET /v1/projects
curl "https://api.webkio.com/v1/projects?limit=25" \
-H "Authorization: Bearer $WEBKIO_API_KEY"
const res = await fetch('https://api.webkio.com/v1/projects?limit=25', {
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
},
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/projects?limit=25');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.get(
'https://api.webkio.com/v1/projects?limit=25',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
)
data = res.json()['data']
Create or update a contact
Matched on email: a new address creates a contact, a known one updates it. Fields you leave out are not changed.
In the API reference: POST /v1/contacts
curl -X POST "https://api.webkio.com/v1/contacts" \
-H "Authorization: Bearer $WEBKIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"project_id":"SITE_ID","email":"sofia@example.com","name":"Sofia Almeida","tags":["vip"]}'
const res = await fetch('https://api.webkio.com/v1/contacts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"project_id": "SITE_ID",
"email": "sofia@example.com",
"name": "Sofia Almeida",
"tags": [
"vip"
]
}),
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/contacts');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'project_id' => 'SITE_ID',
'email' => 'sofia@example.com',
'name' => 'Sofia Almeida',
'tags' => [
'vip',
],
]),
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.post(
'https://api.webkio.com/v1/contacts',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
json={
"project_id": "SITE_ID",
"email": "sofia@example.com",
"name": "Sofia Almeida",
"tags": [
"vip"
]
},
)
data = res.json()['data']
Add an email subscriber
Optionally to a list (GET /email-lists gives their ids). Someone who unsubscribed is never subscribed again this way.
In the API reference: POST /v1/subscribers
curl -X POST "https://api.webkio.com/v1/subscribers" \
-H "Authorization: Bearer $WEBKIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"project_id":"SITE_ID","email":"sofia@example.com","name":"Sofia Almeida","list_id":"LIST_ID"}'
const res = await fetch('https://api.webkio.com/v1/subscribers', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"project_id": "SITE_ID",
"email": "sofia@example.com",
"name": "Sofia Almeida",
"list_id": "LIST_ID"
}),
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/subscribers');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'project_id' => 'SITE_ID',
'email' => 'sofia@example.com',
'name' => 'Sofia Almeida',
'list_id' => 'LIST_ID',
]),
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.post(
'https://api.webkio.com/v1/subscribers',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
json={
"project_id": "SITE_ID",
"email": "sofia@example.com",
"name": "Sofia Almeida",
"list_id": "LIST_ID"
},
)
data = res.json()['data']
Find an order by its number
Orders read exactly as the order webhooks send them.
In the API reference: GET /v1/orders
curl "https://api.webkio.com/v1/orders?number=ORD-260914-0001" \
-H "Authorization: Bearer $WEBKIO_API_KEY"
const res = await fetch('https://api.webkio.com/v1/orders?number=ORD-260914-0001', {
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
},
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/orders?number=ORD-260914-0001');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.get(
'https://api.webkio.com/v1/orders?number=ORD-260914-0001',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
)
data = res.json()['data']
Subscribe a URL to an event
The answer carries the signing secret, shown only this once. Leave project_id out to hear about every site.
In the API reference: POST /v1/webhooks
curl -X POST "https://api.webkio.com/v1/webhooks" \
-H "Authorization: Bearer $WEBKIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"event":"order.paid","target_url":"https://example.com/webkio","project_id":"SITE_ID"}'
const res = await fetch('https://api.webkio.com/v1/webhooks', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"event": "order.paid",
"target_url": "https://example.com/webkio",
"project_id": "SITE_ID"
}),
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/webhooks');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'event' => 'order.paid',
'target_url' => 'https://example.com/webkio',
'project_id' => 'SITE_ID',
]),
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.post(
'https://api.webkio.com/v1/webhooks',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
json={
"event": "order.paid",
"target_url": "https://example.com/webkio",
"project_id": "SITE_ID"
},
)
data = res.json()['data']
Mark an order shipped from your own system
The tracking details are saved with the order, shipping is timestamped, and the customer is emailed, exactly as if you had done it in the dashboard. An order is marked paid by the payment flow and refunded by the refund action, so neither is a status change here.
In the API reference: PATCH /v1/orders/ORDER_ID
curl -X PATCH "https://api.webkio.com/v1/orders/ORDER_ID" \
-H "Authorization: Bearer $WEBKIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"shipped","tracking_number":"TRK-10492","tracking_url":"https://track.example.com/TRK-10492"}'
const res = await fetch('https://api.webkio.com/v1/orders/ORDER_ID', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"status": "shipped",
"tracking_number": "TRK-10492",
"tracking_url": "https://track.example.com/TRK-10492"
}),
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/orders/ORDER_ID');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_POSTFIELDS => json_encode([
'status' => 'shipped',
'tracking_number' => 'TRK-10492',
'tracking_url' => 'https://track.example.com/TRK-10492',
]),
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.patch(
'https://api.webkio.com/v1/orders/ORDER_ID',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
json={
"status": "shipped",
"tracking_number": "TRK-10492",
"tracking_url": "https://track.example.com/TRK-10492"
},
)
data = res.json()['data']
Keep stock in step with your till or warehouse
Say what is actually on the shelf rather than adjusting by a difference, because this call will be retried: a repeated -3 destroys the figure, a repeated 42 is simply true again. Pass variant_id for anything sold by size or colour, since that is where stock lives. You are warned when a product drops INTO its low-stock window, and not again while it stays there, so a nightly sync does not email you nightly.
In the API reference: PUT /v1/products/PRODUCT_ID/stock
curl -X PUT "https://api.webkio.com/v1/products/PRODUCT_ID/stock" \
-H "Authorization: Bearer $WEBKIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"quantity":42}'
const res = await fetch('https://api.webkio.com/v1/products/PRODUCT_ID/stock', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"quantity": 42
}),
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/products/PRODUCT_ID/stock');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => json_encode([
'quantity' => 42,
]),
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.put(
'https://api.webkio.com/v1/products/PRODUCT_ID/stock',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
json={
"quantity": 42
},
)
data = res.json()['data']
Find the product behind an order line
An order line carries a SKU. This is how you turn it into a price, a photograph and what is left. Read variants[].stock when variants is not empty.
In the API reference: GET /v1/products
curl "https://api.webkio.com/v1/products?sku=SKU-114" \
-H "Authorization: Bearer $WEBKIO_API_KEY"
const res = await fetch('https://api.webkio.com/v1/products?sku=SKU-114', {
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
},
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/products?sku=SKU-114');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.get(
'https://api.webkio.com/v1/products?sku=SKU-114',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
)
data = res.json()['data']
List tomorrow's appointments
from and to are the APPOINTMENT date, not when it was booked, and to includes that whole day. This is the call behind "put tomorrow in my calendar" and "text everyone the night before".
In the API reference: GET /v1/bookings
curl "https://api.webkio.com/v1/bookings?from=2026-11-01&to=2026-11-01" \
-H "Authorization: Bearer $WEBKIO_API_KEY"
const res = await fetch('https://api.webkio.com/v1/bookings?from=2026-11-01&to=2026-11-01', {
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
},
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/bookings?from=2026-11-01&to=2026-11-01');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.get(
'https://api.webkio.com/v1/bookings?from=2026-11-01&to=2026-11-01',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
)
data = res.json()['data']
Confirm or cancel an appointment
For when a customer cancels somewhere else. Cancelling refunds a card payment where your policy allows it and emails the customer, the same as cancelling in the dashboard.
In the API reference: PATCH /v1/bookings/BOOKING_ID
curl -X PATCH "https://api.webkio.com/v1/bookings/BOOKING_ID" \
-H "Authorization: Bearer $WEBKIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"confirmed"}'
const res = await fetch('https://api.webkio.com/v1/bookings/BOOKING_ID', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"status": "confirmed"
}),
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/bookings/BOOKING_ID');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_POSTFIELDS => json_encode([
'status' => 'confirmed',
]),
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.patch(
'https://api.webkio.com/v1/bookings/BOOKING_ID',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
json={
"status": "confirmed"
},
)
data = res.json()['data']
See what goes out on hire this week
from and to are the PICKUP date, so this answers "what leaves the yard on Friday". Each reservation names the item it is for.
In the API reference: GET /v1/reservations
curl "https://api.webkio.com/v1/reservations?from=2026-10-31&to=2026-11-07" \
-H "Authorization: Bearer $WEBKIO_API_KEY"
const res = await fetch('https://api.webkio.com/v1/reservations?from=2026-10-31&to=2026-11-07', {
headers: {
Authorization: `Bearer ${process.env.WEBKIO_API_KEY}`,
},
});
const { data } = await res.json();
$ch = curl_init('https://api.webkio.com/v1/reservations?from=2026-10-31&to=2026-11-07');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WEBKIO_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true)['data'];
import os, requests
res = requests.get(
'https://api.webkio.com/v1/reservations?from=2026-10-31&to=2026-11-07',
headers={'Authorization': f"Bearer {os.environ['WEBKIO_API_KEY']}"},
)
data = res.json()['data']