API reference
Every endpoint of the Webkio API, version 1, and every webhook it sends. The same description is at https://api.webkio.com/v1/openapi.json for your own tools. Prefer prose? Read the guide. Ready-made code is in Examples, and how deliveries work in Webhooks.
https://api.webkio.com/v1/openapi.json: in Postman, Import and paste the link; in Insomnia, Import and From URL. Every endpoint arrives ready to send; set the collection's bearer token to your API key.
Conventions
Read a Webkio account's sites, orders and contacts; add contacts, email subscribers and blog post drafts; and subscribe URLs to its events.
Blank fields: in a request body, a field you leave out or send empty changes nothing.
Authentication: an API key (Settings > API & webhooks, or the developer console) as Authorization: Bearer wk_....
Times: every timestamp is ISO 8601 in UTC. The account and each site carry a timezone (IANA) for display; booking and reservation dates and times are the site's local ones.
Lists are cursor-paginated: limit (1-100, default 25) and cursor (the previous page's meta.next_cursor) until meta.has_more is false.
Errors are {"success": false, "error": {"code": "...", "message": "..."}}. Branch on the code:
missing_api_key: No key was sent.invalid_api_key: The key is unknown or revoked.console_token_expired: The developer site's temporary token has expired; reload the explorer.account_unavailable: The account is deleted, suspended or banned.plan_required: The account's plan does not include integrations, or the feature the endpoint uses (the CRM, the blog).plan_limit_reached: A limit of the plan is reached: new subscribers this month, or blog posts on a site.read_only_demo: The demo account cannot change anything.rate_limited: Over 200 requests a minute. Retry-After says when to come back.not_found: No such endpoint.resource_not_found: No such record on this account.unknown_event: The event type is not one GET /v1/event-types lists.invalid_target_url: The webhook URL is not https, not public, or too long.invalid_project: project_id is not one of this account's sites.invalid_list: list_id is not one of the site's email lists.email_rejected: Webkio does not send email to that address: it bounced or complained before, or it is a throwaway address.webhook_limit_reached: The account already has 50 webhooks.invalid_cursor: The cursor was not one this API gave out.validation_failed: The request was understood but not accepted; the message says why.server_error: Something failed on our side.
200 requests a minute per account. Guide: https://webkio.com/docs/api-and-webhooks
Account
Who the key belongs to, and their sites.
The account the key belongs to
Integrations call this to test a connection.
200The account.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
The account's sites
| Parameter | In | Type | Description |
|---|---|---|---|
limit | query | integer | |
cursor | query | string | The previous page's meta.next_cursor. |
200Sites, oldest first.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Webhooks
Event types, sample data, and subscriptions.
The events a webhook can subscribe to
The whole list; it is short and not paginated.
200Every event type.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Newest records for an event type
Your own newest records, in exactly the shape a webhook delivers them.
| Parameter | In | Type | Description |
|---|---|---|---|
typerequired | path | one of order.created, order.paid, booking.created, rental.reserved, subscriber.created, property_enquiry.created, review.submitted | |
project_id | query | string | Only this site. |
limit | query | integer |
200Newest first.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
The account's webhooks
| Parameter | In | Type | Description |
|---|---|---|---|
limit | query | integer | |
cursor | query | string | The previous page's meta.next_cursor. |
200Newest first.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Subscribe a URL to an event
The URL must be https and public. Subscribing the same URL to the same event again returns the existing webhook. The signing secret is returned only here.
| Body field | Type | Description |
|---|---|---|
eventrequired | one of order.created, order.paid, booking.created, rental.reserved, subscriber.created, property_enquiry.created, review.submitted | |
target_urlrequired | string (uri) | |
project_id | string | Only this site. Leave out for every site. |
201The webhook, with its secret.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
One webhook
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
200The webhook (without its secret).401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Remove a webhook
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
200Removed.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Contacts
The CRM's people, matched on email within a site. Plans with the CRM.
Find contacts
Newest first. Pass email to find one person.
| Parameter | In | Type | Description |
|---|---|---|---|
project_id | query | string | Only this site. |
email | query | string (email) | Only the contact with this email. Not case-sensitive. |
limit | query | integer | |
cursor | query | string | The previous page's meta.next_cursor. |
200Contacts, newest first.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Create or update a contact
Matched on email within the site: an email the site does not know creates a contact (201), a known one updates it (200). name, phone and notes replace what is stored; tags are added to the contact's own.
| Body field | Type | Description |
|---|---|---|
project_idrequired | string | The site, from GET /v1/projects. |
emailrequired | string (email) | What the contact is matched on. |
name | string | |
phone | string | |
notes | string | Replaces the contact's notes. |
tags | list of string or string | A list, or one text with commas between the tags. |
200The updated contact.201The new contact.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
One contact
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
200The contact.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Email subscribers and lists.
Add an email subscriber
Adds the address to the site's subscribers, active at once, and to list_id when sent. Only send people who agreed to hear from the site. Someone already subscribed is not added twice (200): they join the list, gain the tags and keep their status, so an address that unsubscribed stays unsubscribed. A new subscriber (201) counts toward the plan's monthly limit and starts the site's welcome automation.
| Body field | Type | Description |
|---|---|---|
project_idrequired | string | The site, from GET /v1/projects. |
emailrequired | string (email) | |
name | string | |
tags | list of string or string | A list, or one text with commas between the tags. |
list_id | string | Also add them to this list, from GET /v1/email-lists. |
200Already subscribed.201The new subscriber.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Email lists
| Parameter | In | Type | Description |
|---|---|---|---|
project_id | query | string | Only this site. |
limit | query | integer | |
cursor | query | string | The previous page's meta.next_cursor. |
200Lists, oldest first.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Blog
Blog post drafts, to publish from the dashboard.
Create a blog post draft
Always a draft: it is published from the dashboard, where it is checked before it goes live. The slug is made from the title unless you send one, and kept unique on the site. content is HTML; scripts and unsafe markup are removed.
| Body field | Type | Description |
|---|---|---|
project_idrequired | string | The site, from GET /v1/projects. |
titlerequired | string | |
content | string | HTML. Scripts and unsafe markup are removed. |
excerpt | string | |
slug | string | Made from the title when left out. |
tags | list of string or string | A list, or one text with commas between the tags. |
meta_title | string | |
meta_description | string | |
featured_image | string (uri) |
201The draft.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Orders
Orders, read only.
Find orders
Newest first. Each order reads as the order webhooks send it.
| Parameter | In | Type | Description |
|---|---|---|---|
project_id | query | string | Only this site. |
number | query | string | The order number, exactly. |
email | query | string (email) | The customer's email. Not case-sensitive. |
status | query | one of pending, paid, processing, shipped, delivered, refunded, cancelled | |
limit | query | integer | |
cursor | query | string | The previous page's meta.next_cursor. |
200Orders, newest first.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
One order
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
200The order.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Move an order's status on
Moves the order and does what goes with it: tracking details are saved, shipping is timestamped, a cancellation puts the stock back, and the customer is emailed - the same as a change made in the dashboard. An order is marked paid by the payment flow and refunded by the refund action, so neither is settable here.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
| Body field | Type | Description |
|---|---|---|
statusrequired | one of processing, shipped, delivered, cancelled | |
tracking_number | string | Saved against the order; usually sent with shipped. |
tracking_url | string (uri) |
200The updated order.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Products
Find products
Newest first. Includes products that have been switched off, so a catalogue sync can withdraw them too - filter with active if you only want the ones on sale. Stock lives on the variant for anything sold by size or colour, so read variants[].stock when variants is not empty.
| Parameter | In | Type | Description |
|---|---|---|---|
project_id | query | string | Only this site. |
sku | query | string | The SKU, exactly. How you find the product behind an order line. |
type | query | one of physical, digital, service, bundle | |
category_id | query | string | |
active | query | boolean | Omit for both. |
search | query | string | Matches name or SKU. |
limit | query | integer | |
cursor | query | string | The previous page's meta.next_cursor. |
200Products, newest first.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
One product
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
200The product.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Set what is in stock
States the real count rather than adjusting by a difference, because every caller retries: a repeated -3 destroys the figure, a repeated = 42 is simply true again. Pass variant_id for anything sold by size or colour. The owner is warned when a product drops INTO its low-stock window, and not again while it stays there, so a nightly sync does not email them nightly. Refused on a product that does not track stock.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
| Body field | Type | Description |
|---|---|---|
quantityrequired | integer | Whole number, zero or more. |
variant_id | string | Required for a product with variants, since stock lives there. |
200The updated product.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Bookings
Find bookings
Newest first. Each booking reads as the booking.created webhook sends it. from/to filter the APPOINTMENT date, not when it was made.
| Parameter | In | Type | Description |
|---|---|---|---|
project_id | query | string | Only this site. |
email | query | string (email) | The customer's email. Not case-sensitive. |
status | query | one of pending, confirmed, cancelled, completed, no-show | |
from | query | string (date) | Appointments on or after this date (YYYY-MM-DD). |
to | query | string (date) | Appointments on or before this date (YYYY-MM-DD). |
limit | query | integer | |
cursor | query | string | The previous page's meta.next_cursor. |
200Bookings, newest first.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
One booking
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
200The booking.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Change a booking's status
Moves the booking and does everything that goes with it: a cancellation refunds a card payment where the policy allows, and the customer is emailed - the same as a change made in the dashboard.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
| Body field | Type | Description |
|---|---|---|
statusrequired | one of pending, confirmed, cancelled, completed, no-show |
200The updated booking.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Reservations
Find rental reservations
Newest first. Each reservation reads as the rental.reserved webhook sends it. from/to filter the PICKUP date, not when the reservation was taken.
| Parameter | In | Type | Description |
|---|---|---|---|
project_id | query | string | Only this site. |
reference | query | string | The reservation reference, exactly. |
email | query | string (email) | The customer's email. Not case-sensitive. |
status | query | one of pending, confirmed, cancelled, completed | |
from | query | string (date) | Pick-ups on or after this date (YYYY-MM-DD). |
to | query | string (date) | Pick-ups on or before this date (YYYY-MM-DD). |
limit | query | integer | |
cursor | query | string | The previous page's meta.next_cursor. |
200Reservations, newest first.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
One reservation
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
200The reservation.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Change a reservation's status
Moves the reservation and does everything that goes with it: a cancellation refunds a card payment where the policy allows, releases the deposit hold, and emails the customer - the same as a change made in the dashboard.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
| Body field | Type | Description |
|---|---|---|
statusrequired | one of pending, confirmed, cancelled, completed |
200The updated reservation.401missing_api_key, invalid_api_key or console_token_expired.403account_unavailable, plan_required, plan_limit_reached or read_only_demo.404resource_not_found, unknown_event or not_found.422unknown_event, invalid_target_url, invalid_project, invalid_list, email_rejected, webhook_limit_reached, invalid_cursor or validation_failed.429rate_limited: over 200 requests a minute. Retry-After says when to come back.
Webhook events
What Webkio sends to a URL you subscribe with POST /v1/webhooks. The payload of each, its headers and the signature check are on Webhooks.
| Event | Sent when |
|---|---|
order.created | An order is placed in your shop. Card payments may still be pending. Sent to every URL subscribed to order.created, signed with that subscription's secret. |
order.paid | Payment for an order is confirmed. Sent to every URL subscribed to order.paid, signed with that subscription's secret. |
booking.created | A customer books an appointment. Sent to every URL subscribed to booking.created, signed with that subscription's secret. |
rental.reserved | A customer reserves a rental item. Sent to every URL subscribed to rental.reserved, signed with that subscription's secret. |
subscriber.created | Someone joins your email list. Sent to every URL subscribed to subscriber.created, signed with that subscription's secret. |
property_enquiry.created | A visitor enquires about a property listing. Sent to every URL subscribed to property_enquiry.created, signed with that subscription's secret. |
review.submitted | A customer reviews a product. Sent to every URL subscribed to review.submitted, signed with that subscription's secret. |