Create an agreement
Books the customer into the units named, as a `draft` agreement. Each unit is checked, under a lock, by the same rule every hold, booking and transfer uses: a unit that is archived, not in service (occupied, under maintenance, overlocked or unavailable), already booked, or held for someone else is refused with a 409 that says which, and nothing is created. A unit reserved for this same customer is not refused: the booking takes that reservation up, whether or not `reservation_id` names it. One agreement takes up at most one reservation, so a booking of two reserved units is refused (422) — book each on its own. Refusing held, archived and out-of-service units is a tightening made on 27 September 2026; such units were booked before.
Books the customer into the units named, as a draft agreement. Each unit is checked, under a lock, by the same rule every hold, booking and transfer uses: a unit that is archived, not in service (occupied, under maintenance, overlocked or unavailable), already booked, or held for someone else is refused with a 409 that says which, and nothing is created. A unit reserved for this same customer is not refused: the booking takes that reservation up, whether or not reservation_id names it. One agreement takes up at most one reservation, so a booking of two reserved units is refused (422) — book each on its own. Refusing held, archived and out-of-service units is a tightening made on 27 September 2026; such units were booked before.
Present an API key (sb_live_… / sb_test_…), an OAuth2 access token, or a static token as a Bearer credential. The operator is implied by the credential; it is never in the path. Only a SHA-256 hash of an API key is stored server-side.
In: header
Header Parameters
A unique key that makes this mutation safe to retry. Repeats replay the stored response; reuse with a different body returns 409 idempotency_conflict.
length <= 255Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/agreements" \ -H "Content-Type: application/json" \ -d '{ "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811", "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598" }'{ "data": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "agreement", "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811", "unit_id": "5becc822-b69e-4e66-a762-ad8e868dcab6", "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598", "order_id": "93101167-9065-4b9c-b98b-5d789a3ed9fe", "number": "string", "status": "quote", "licence_fee_minor": 0, "currency": "str", "billing_interval": "week", "move_in_date": "2019-08-24", "move_out_date": "2019-08-24", "notice_given_at": "2019-08-24T14:15:22Z", "notice_period_days": 0, "terminated_at": "2019-08-24T14:15:22Z", "contract_id": "9aafc1a8-e497-46c9-ba0b-bd5b03c353e4", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "reservation_id": "b947feb5-3593-40ee-8244-4428da3fe32d" }}{ "data": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "object": "agreement", "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811", "unit_id": "5becc822-b69e-4e66-a762-ad8e868dcab6", "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598", "order_id": "93101167-9065-4b9c-b98b-5d789a3ed9fe", "number": "string", "status": "quote", "licence_fee_minor": 0, "currency": "str", "billing_interval": "week", "move_in_date": "2019-08-24", "move_out_date": "2019-08-24", "notice_given_at": "2019-08-24T14:15:22Z", "notice_period_days": 0, "terminated_at": "2019-08-24T14:15:22Z", "contract_id": "9aafc1a8-e497-46c9-ba0b-bd5b03c353e4", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "reservation_id": "b947feb5-3593-40ee-8244-4428da3fe32d" }}{ "error": { "code": "unauthorized", "message": "Missing or invalid credential." }}{ "error": { "code": "insufficient_scope", "message": "The credential lacks a scope required by this endpoint." }}{ "error": { "code": "unit_reserved", "message": "A12 is reserved for Priya Shah until 6th Oct ’26." }}{ "error": { "code": "validation_error", "message": "That reservation holds a different unit.", "details": [ { "field": "reservation_id", "issue": "holds a different unit" } ] }}{ "error": { "code": "rate_limited", "message": "Rate limit exceeded. Retry after 7s." }}{ "error": { "code": "validation_error", "message": "string", "details": [ { "field": "string", "issue": "string" } ] }}Change the renewal date POST
Moves the day the customer renews on, from now on. Nothing already invoiced changes. By default the next renewal bills a shortened period, from next_billing_date up to the day before the new renewal date, pro-rated by day against the full period it replaces; full periods then run from the new date. That change is pending until the next renewal invoice is raised, is shown in pending_renewal_change, and can be cancelled with DELETE until then. A second change replaces a pending one. With waive true, the days are not charged: the current invoice's period is extended to cover them and the new schedule applies at once, so nothing is pending. Send day for monthly, quarterly, six-monthly and yearly subscriptions, and date for weekly and 4-weekly ones. No email is sent to the customer; the renewal invoice describes the change. Fires subscription.renewal_date_changed.
Create a contact POST
Next Page