partner

POST /v1/partner/customers/{externalId}/addon-orders

Place an add-on order for one of your customer's existing sites, unpaid.

All partner endpoints

All developer docs →

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

NameTypeRequiredWhat it is
externalId (path)stringYesYOUR 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)stringNoClient-generated key that makes an unsafe request replay-safe: the server stores the first response and returns it verbatim for repeats.

Request body

NameTypeRequiredWhat it is
site_idstringYesThe customer's site the add-ons are for. Its product line decides what is sold.
currencystringYes—
addonsobject[]Yes—
billing_countrystringNoOverrides the country on the customer's billing profile for this order.
return_urlstringYesAs on a domain order.
cancel_urlstringYesAs on a domain order.
localestringNoThe language the payment page opens in.

Response

NameTypeRequiredWhat it is
order_idstringYes—
human_refstringYesThe reference the payment page returns to you as ?order=.
pay_urlstringNoOnly 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_atstringNo—
org_idstringYes—
statusstringYesAs on PartnerOrder.
currencystringYes—
site_idobjectYesThe site the add-ons are for.
subtotal_minorintegerYes—
tax_minorintegerYes—
total_minorintegerYes—
linesPartnerAddonOrderLine[]Yes—

Errors this endpoint can return

401 · 403 · 404 · 422 · 429