partner
POST /v1/partner/customers/{externalId}/addon-orders
Place an add-on order for one of your customer's existing sites, unpaid.
Authentication
Send an API key as a bearer token. The key must carry the partner.domains permission; a key without it is refused with 403, not 404.
This endpoint takes no organisation id. Your key already identifies the organisation it belongs to, and the response is scoped to it.
Try it
Replace anything in angle brackets with your own values, and the key placeholder with a key from your dashboard.
curl -X POST https://api.zinndigital.com/v1/partner/customers/{externalId}/addon-orders \
-H "Authorization: Bearer zdk_live_…" \
-H "Content-Type: application/json" \
-d '{ "site_id": <string>, "currency": <string>, "addons": <object[]>, "return_url": <string>, "cancel_url": <string> }'Signed in? The API console in your dashboard fills in your real organisation id and your own key, and runs the request against the live API so you can see the actual response. Open this endpoint in the API console
Details
The hosting order with the plan taken away, and the same safety properties: priced from our catalogue in currency, placed pending_payment, nothing charged and no payment method touched; the customer pays on the hosted page named by pay_url (a secret shown only in this response). return_url and cancel_url follow the same allowlist rules. Idempotency-Key is required — a retry returns the same order with a fresh pay_url. Site. site_id is one of the customer's sites. Its product line decides what may be sold — the same rule a hosting order applies to its plan's line, from the same resolver, and the one listCatalogAddons publishes (product_lines, excluded_product_lines). Once paid, each add-on is created for THAT site and delivered by the same fulfilment a purchase in the customer's dashboard uses; getPartnerAddonOrder then returns each line's purchase_id and purchase_status. Refusals carry a stable details[0].code: site_unknown (no such site, or not one you can reach), site_not_yours (it belongs to another customer of yours — a crossed reference on your side), site_unavailable (being deleted, deleted, or never built), not_in_good_standing (the customer holds no active hosting to add to), addons_required, too_many_addons, addon_unknown, addon_not_offered (not sold on this site's product line, or a website slot for a line the customer has no plan on), addon_currency, return_url_not_allowed, not_linked. The set is published in getPartnerCapabilities as hosting_orders.addon_order_refusal_codes. There is no per-add-on quantity: a repeated code is bought once. Requires partner.domains.
Parameters
| Name | Type | Required | What it is |
|---|---|---|---|
externalId (path) | string | Yes | YOUR id for that customer — whatever your own system calls them. It is what makes linking idempotent, and it is scoped to your partner programme: another partner's id is a 404… |
Idempotency-Key (header) | string | No | Client-generated key that makes an unsafe request replay-safe: the server stores the first response and returns it verbatim for repeats. |
Request body
| Name | Type | Required | What it is |
|---|---|---|---|
site_id | string | Yes | The customer's site the add-ons are for. Its product line decides what is sold. |
currency | string | Yes | — |
addons | object[] | Yes | — |
billing_country | string | No | Overrides the country on the customer's billing profile for this order. |
return_url | string | Yes | As on a domain order. |
cancel_url | string | Yes | As on a domain order. |
locale | string | No | The language the payment page opens in. |
Response
| Name | Type | Required | What it is |
|---|---|---|---|
order_id | string | Yes | — |
human_ref | string | Yes | The reference the payment page returns to you as ?order=. |
pay_url | string | No | Only in the response that placed (or replayed) the order: the hosted page the customer pays on. It carries a secret that is stored nowhere — treat it as one. |
pay_expires_at | string | No | — |
org_id | string | Yes | — |
status | string | Yes | As on PartnerOrder. |
currency | string | Yes | — |
site_id | object | Yes | The site the add-ons are for. |
subtotal_minor | integer | Yes | — |
tax_minor | integer | Yes | — |
total_minor | integer | Yes | — |
lines | PartnerAddonOrderLine[] | Yes | — |
Errors this endpoint can return
401 · 403 · 404 · 422 · 429