Provision a customer and order
Creates or updates, in one transaction, the customer, an optional contact, the products and a draft or active order of a deal closed in your CRM, each matched by your externalId. Products are upserted with the attributes you send (matched by name), and each order line is priced from its attributes, else its planId, else the product's default plan. Re-provisioning a draft order replaces its lines, keeping the IDs of lines whose externalId matches; an order that is already active answers 409 ORDER_ALREADY_ACTIVE, so change it with amendments. Provisioning an order as active activates it as Activate an order does, so it answers 409 CUSTOMER_HAS_ACTIVE_ORDER (and nothing is created or changed) when another of the customer's active orders, on a different product, prices one of the same events, and 409 ORDER_BILLED_IN_STRIPE likewise when the order starts before today and would replace an order billed through a Stripe subscription. A contact belongs to one customer: a contact.externalId that is another customer's contact answers 409 CONTACT_CUSTOMER_IMMUTABLE, and billing contacts that aren't the customer's or the billing customer's answer 400. The Idempotency-Key header is required: a retry with the same key and body answers exactly as the first call did, and the same key with a different body answers 409 IDEMPOTENCY_KEY_REUSED. Answers 201 when the order is created and 200 when an existing draft order is updated.
Headers
- Type: stringIdempotency
- Key min length:1requiredA key unique to this deal and version of it, such as the CRM deal ID plus a revision. A retry with the same key and body answers as the first call did; the same key with a different body answers 409.
Body·
- Type:customerrequiredProperties: 7
The customer, matched by
externalId(case-insensitively) and created if new. On a match,nameis replaced and the other fields only when you send them. - Type: objectexternal
Reference requiredProperties: 3Where the deal comes from.
- Properties: 18Type:orderrequired
- Type:contactProperties: 6
A contact at the customer, matched by
externalIdand created if new; on a match every field is replaced by what you send. Answers 409CONTACT_CUSTOMER_IMMUTABLEwhen theexternalIdis another customer's contact. It becomes the order's billing contact unlessorder.billingContactExternalIdsnames others. Afterwards it is an ordinary contact: read or change it with Get a contact by external ID and Update a contact by external ID.
Responses
- application/json
- application/json
- application/json
- application/json
curl https://billing.getspondo.com/api/v1/provision \
--request POST \
--header "Authorization: Bearer $SPONDO_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: sf-0065g00000AbCdE-v1" \
--data '{
"externalReference": { "source": "salesforce", "id": "0065g00000AbCdE" },
"customer": { "name": "Acme Legal LLP", "externalId": "acme-legal", "email": "billing@acmelegal.com" },
"contact": { "externalId": "acme-legal-ap", "firstName": "Priya", "lastName": "Shah", "email": "ap@acmelegal.com" },
"order": {
"externalId": "sf-0065g00000AbCdE",
"name": "DocuMind Growth renewal",
"currency": "USD",
"startDate": "2026-12-01",
"endDate": "2027-11-30",
"paymentTerms": "Net30",
"lines": [
{
"externalId": "sf-0065g00000AbCdE-1",
"startDate": "2026-12-01",
"product": {
"name": "DocuMind",
"externalId": "documind",
"attributes": [
{
"name": "Platform fee",
"pricing": {
"chargeType": "recurring",
"pricingModel": "perUnit",
"billingFrequency": "monthly",
"pricePoints": { "currency": "USD", "unitPrice": 49900 }
},
"creditBenefits": [{ "amount": 50000, "overageUnitPrice": 0.2 }]
}
]
},
"attributes": [
{ "name": "Platform fee", "discountPercent": 10 },
{ "name": "Document uploads" }
]
}
]
}
}'
{
"status": "updated",
"createdAt": "2026-11-10T08:02:44.000Z",
"customer": {
"id": "cus_Q2x9vB7mK4pT1sLw",
"provisionStatus": "updated",
"createdAt": "2026-09-14T16:20:05.000Z"
},
"contact": {
"id": "con_Lw5Xa9Su3Zo7Cr2N",
"provisionStatus": "updated",
"createdAt": "2026-11-09T10:15:00.000Z"
},
"order": {
"id": "ord_6Wd2Hs9Kx4Mp7Qt1",
"provisionStatus": "updated",
"createdAt": "2026-11-09T10:15:00.000Z",
"lines": [
{
"id": "8d0f2b4c-6e8a-4c1d-9f3b-5a7c9e1d3f5b",
"externalId": "sf-0065g00000AbCdE-1",
"provisionStatus": "updated",
"createdAt": "2026-11-09T10:15:00.000Z",
"lineType": "STANDARD"
}
]
}
}