Parent & child
A parent-child relationship links two customer records so that one customer, the parent, pays for another's subscriptions. A head office with one contract and a customer record per site is the usual shape. The relationship lives on the customer, not on the subscription: each child keeps its own subscriptions with their own products, cadence and stable ids, and the parent decides how their charges are invoiced.
A parent-child relationship is not a billing group.
A group joins several of one customer's subscriptions onto one shared invoice;
parent-child spans two customers. The two do not combine on one customer: a
customer billed to a parent cannot hold a group, and a customer holding a group
cannot be billed to a parent. Either attempt answers
400 SUBSCRIPTION_BILLING_GROUP_CUSTOMER_BILLED_TO_PARENT.
The fields
Four fields on the customer, all readable on GET /v1/customers/{customerId}
and writable on PATCH /v1/customers/{customerId} (scope customers-write, see
the API Reference):
| Field | On | Meaning |
|---|---|---|
parentCustomerId | the child | The parent this customer is billed to. null detaches it. |
billingRelationship | the child | self bills the customer directly. parent_pays bills the parent instead. Set together with parentCustomerId. |
consolidationMode | the parent | single_invoice puts every child's charges on one parent invoice on billingDay. per_child_invoice issues one invoice per child, addressed to the parent. |
billingDay | the parent | Day of month, 1 to 28, the consolidated invoice is generated on. Required for single_invoice. |
The parent's own subscriptions, if any, are unaffected by its children.
List a parent's children
GET /v1/customers?parentCustomerId={parentId} returns every customer whose
parentCustomerId is that id. The list is not paginated.
Acknowledge the affected subscriptions
Moving a child under a parent that invoices as single_invoice moves every
active subscription on the child onto the parent's billingDay, with a clean
cut dated today. The request has to say that it knows this: it carries
subscriptionTransitions, one entry per subscription, using the id
GET /v1/subscriptions?customerId={childId} returns. That is the same stable
id every other subscription endpoint takes.
Send every id that list returns. An entry for a subscription that needs no
transition is accepted and ignored. An omitted one is refused with
CUSTOMER_TRANSITION_MISSING_SUBSCRIPTIONS, and the response names the missing
ids. An id that belongs to another customer is refused with
CUSTOMER_TRANSITION_INVALID_SUBSCRIPTION. A child with no active
subscriptions needs no array, and per_child_invoice needs no transitions.
Code
A parent-side change needs the same acknowledgement for every child: switching
the parent to single_invoice, or moving its billingDay, re-dates every
child's subscriptions. List the children with
GET /v1/customers?parentCustomerId={parentId}, then
GET /v1/subscriptions?customerId={childId} for each, and send the union.
What changes on the invoice
consolidationMode | The parent receives | On the invoice |
|---|---|---|
single_invoice | One invoice on billingDay, covering every child's subscriptions | isConsolidated: true, customerSubscriptionId: null, billingGroupId: null |
per_child_invoice | One invoice per child, on each child's own dates | customerSubscriptionId set to that child's subscription |
The billed event fires once per child subscription on a consolidated invoice,
each carrying the whole invoice total; deduplicate on invoiceId. The
reconciliation rule is on
Webhooks & reconciliation.
No customer event fires for a hierarchy change. Read the customer back to confirm it.
Errors & failure states
| Condition | What you observe | Fix |
|---|---|---|
The child has active subscriptions and the request carries no subscriptionTransitions | 400 CUSTOMER_TRANSITION_REQUIRED_FOR_ACTIVE_SUBSCRIPTIONS | List the child's subscriptions and send one entry per id. |
| An active subscription is missing from the array | 400 CUSTOMER_TRANSITION_MISSING_SUBSCRIPTIONS, details.missingSubscriptionIds | Add the named ids and resend. |
| An id belongs to another customer, or is repeated | 400 CUSTOMER_TRANSITION_INVALID_SUBSCRIPTION, details.invalidSubscriptionIds or details.duplicateSubscriptionIds | Send each of the child's own subscription ids once. |
| The customer holds a billing group and is being billed to a parent | 400 SUBSCRIPTION_BILLING_GROUP_CUSTOMER_BILLED_TO_PARENT | Dissolve the group first, or keep the customer billing on its own. |
parentCustomerId names no customer in your company | 404 CUSTOMER_NOT_FOUND | Send the id GET /v1/customers returns for the parent. |
parentCustomerId is the customer's own id | 400 CUSTOMER_CIRCULAR_PARENT_REFERENCE | Pick a different customer as the parent. |
| The named parent is itself a child, or the customer has children of its own | 400 CUSTOMER_CHILD_CANNOT_BE_PARENT | A hierarchy is one level deep. Detach the other relationship first. |
consolidationMode is single_invoice and no billingDay is set, on the parent being updated or on the parent a child joins | 400 CUSTOMER_BILLING_DAY_REQUIRED_FOR_SINGLE_INVOICE | Set billingDay on the parent, in the same request or before. |
| The parent has no way to receive invoices for the child's active subscriptions | 400 CUSTOMER_PARENT_CANNOT_DELIVER_FOR_CHILD, details.parentCustomerId, details.childCustomerId, details.affectedSubscriptionCount | Give the parent an email or an invoice-delivery contact before routing billing to it. |
A parent-paid child with active subscriptions is detached, or set back to self, and has no email of its own | 400 CUSTOMER_CANNOT_REVERT_TO_SELF_PAY_NO_DELIVERY | Send email in the same request, or give the child a delivery contact first. |
POST /v1/subscriptions targets a parent-paid child whose parent invoices as single_invoice without a billingDay | 400 CUSTOMER_PARENT_NOT_CONFIGURED | Set the parent's billingDay, then assign again. |