Create or replace the customer's billing profile
const url = 'http://localhost:8080/v1/customers/example/billing-profile';const options = { method: 'PUT', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"legal_name":"example","phone":"example","address_line1":"example","address_line2":"example","city":"example","state":"example","postal_code":"example","country":"example","currency":"example","tax_status":"standard","tax_exempt_reason":"example","tax_id":"example","tax_id_type":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url http://localhost:8080/v1/customers/example/billing-profile \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "legal_name": "example", "phone": "example", "address_line1": "example", "address_line2": "example", "city": "example", "state": "example", "postal_code": "example", "country": "example", "currency": "example", "tax_status": "standard", "tax_exempt_reason": "example", "tax_id": "example", "tax_id_type": "example" }'Writes the whole profile. Fields you leave out are stored empty,
so send every field you want to keep. profile_status is worked
out by the server: ready when legal name, address line 1, city
and country are all set, otherwise incomplete.
Checks, each answered with 422 and param set to the field:
country must be an ISO 3166 alpha-2 code; currency must be a
supported ISO 4217 code (zero-decimal currencies such as JPY are
refused); phone is 7 to 20 digits, spaces or +-(); tax_id
must match tax_id_type when the type is a known one;
tax_status: exempt needs tax_exempt_reason;
tax_status: reverse_charge needs tax_id. Country and currency
are stored in upper case.
A currency that differs from the plan currency of a subscription
that still bills is refused with 409 invalid_state, because
invoices would show plan prices in the new currency without
conversion.
After saving, the profile is copied to the linked Stripe customer (best effort), and draft invoices whose tax failed on bad customer data are retried. The change is written to the audit log.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Header Parameters
Section titled “Header Parameters”Makes the call safe to retry. Send a unique value (a UUID works) and
the same value on every retry. For 24 hours, a repeat with the same
key, method, path and body gets the first response again, with an
Idempotent-Replayed: true header, instead of running again. The
error cases are in docs/api-surface.md. The usage routes do not take
it: each usage event carries its own idempotency_key.
Request Bodyrequired
Section titled “Request Bodyrequired”The billing details printed on invoices and used for tax. The whole profile is replaced on every write.
object
7 to 20 characters of digits, spaces, +, -, (, ).
ISO 3166 alpha-2 code, such as US or IN.
ISO 4217 code, such as USD. When set, invoices for this
customer use it instead of the plan currency.
Defaults to standard.
Required when tax_status is exempt.
Buyer tax ID. Required when tax_status is reverse_charge.
Tax ID kind, stored as its Stripe code (for example eu_vat, in_gst).
Responses
Section titled “Responses”The stored profile.
object
7 to 20 characters of digits, spaces, +, -, (, ).
ISO 3166 alpha-2 code, such as US or IN.
ISO 4217 code, such as USD. When set, invoices for this
customer use it instead of the plan currency.
Defaults to standard.
Required when tax_status is exempt.
Buyer tax ID. Required when tax_status is reverse_charge.
Tax ID kind, stored as its Stripe code (for example eu_vat, in_gst).
Set by the server. ready when legal name, address line
1, city and country are all set.
Example
{ "tax_status": "standard", "profile_status": "incomplete"}The body is not valid JSON.
object
object
One of invalid_request_error, authentication_error,
rate_limit_error or api_error. Every error the API
answers has this shape, including an unknown path (404,
code route_not_found) and a method the path does not take
(405, code method_not_allowed, with an Allow header).
The few exceptions are listed in docs/api-surface.md.
The request field the error is about. Sent only when the error
names one. A request body may hold only the fields its
operation lists, spelled and cased as listed: any other
field, or one the server sets (such as id), is refused
with 422 and param naming it. An operation with no request body lists no fields: send
no body, {} or null. The Stripe and Postmark webhooks and
the LiteLLM callback take their sender’s body as it comes.
Example
{ "error": { "type": "invalid_request_error" }}Customer not found.
object
object
One of invalid_request_error, authentication_error,
rate_limit_error or api_error. Every error the API
answers has this shape, including an unknown path (404,
code route_not_found) and a method the path does not take
(405, code method_not_allowed, with an Allow header).
The few exceptions are listed in docs/api-surface.md.
The request field the error is about. Sent only when the error
names one. A request body may hold only the fields its
operation lists, spelled and cased as listed: any other
field, or one the server sets (such as id), is refused
with 422 and param naming it. An operation with no request body lists no fields: send
no body, {} or null. The Stripe and Postmark webhooks and
the LiteLLM callback take their sender’s body as it comes.
Example
{ "error": { "type": "invalid_request_error" }}Currency conflicts with a billing subscription’s plan currency (invalid_state).
object
object
One of invalid_request_error, authentication_error,
rate_limit_error or api_error. Every error the API
answers has this shape, including an unknown path (404,
code route_not_found) and a method the path does not take
(405, code method_not_allowed, with an Allow header).
The few exceptions are listed in docs/api-surface.md.
The request field the error is about. Sent only when the error
names one. A request body may hold only the fields its
operation lists, spelled and cased as listed: any other
field, or one the server sets (such as id), is refused
with 422 and param naming it. An operation with no request body lists no fields: send
no body, {} or null. The Stripe and Postmark webhooks and
the LiteLLM callback take their sender’s body as it comes.
Example
{ "error": { "type": "invalid_request_error" }}A field failed validation, or the body has a key the profile does
not have, such as tax_exempt (set tax_status instead), or one
the server sets, such as customer_id or created_at. param
names the field.
object
object
One of invalid_request_error, authentication_error,
rate_limit_error or api_error. Every error the API
answers has this shape, including an unknown path (404,
code route_not_found) and a method the path does not take
(405, code method_not_allowed, with an Allow header).
The few exceptions are listed in docs/api-surface.md.
The request field the error is about. Sent only when the error
names one. A request body may hold only the fields its
operation lists, spelled and cased as listed: any other
field, or one the server sets (such as id), is refused
with 422 and param naming it. An operation with no request body lists no fields: send
no body, {} or null. The Stripe and Postmark webhooks and
the LiteLLM callback take their sender’s body as it comes.
Example
{ "error": { "type": "invalid_request_error" }}