Skip to content

Brands tools

MCP tools for Brands: brands_create, brands_domains_add, brands_domains_list, brands_domains_remove, brands_domains_verify, brands_get, brands_go_live, brands_go_live_checklist, brands_list, brands_update.

  • brands_create: Create a brand
  • brands_domains_add: Add a custom domain to a brand
  • brands_domains_list: List a brand's custom domains
  • brands_domains_remove: Remove a custom domain from a brand
  • brands_domains_verify: Check a custom domain again
  • brands_get: Get a brand
  • brands_go_live: Take a brand live
  • brands_go_live_checklist: Get a brand's go-live checklist
  • brands_list: List brands
  • brands_update: Update a brand

brands_create

Create a brand. Operation brands.create · Organization level · permission brands:write · risk tier write · since M1

Creates a brand (a storefront or product line) under one of the organization's legal entities. The brand starts in test mode only (status: test_only); it goes live through the go-live checklist.

  • slug is unique across Ownrecord: it appears in checkout URLs and API keys.
  • invoiceSeries.invoice (and creditNote, default {invoice}-CN) must be unused by every other brand of the same entity: each brand numbers its invoices in its own series within the entity.
  • statementDescriptor defaults to the name in capitals.

The plan limits the number of brands (brands.max). Needs brands:write: organization owners and admins, or an org or entity API key with that scope (a test-mode key creates the brand like any other key: brands aren't mode-separated).

Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: false · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
entityIdID (ent_…)yes–
namestringyes(1–120 characters)
slugstringyes(3–40 characters)
invoiceSeriesobjectyes–
statementDescriptorstringno(5–22 characters)
brandingobjectno–
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
idempotency_keystringnoA unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters)
dry_runbooleannotrue: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false)
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Idempotency: the result returns the idempotency_key used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
  • Dry run: supported. dry_run: true checks permissions and rules and computes the result, then rolls everything back.

Errors

Examples

A brand with its own invoice series

Arguments:

JSON
{
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "name": "Acme App",
  "slug": "acme-app",
  "invoiceSeries": {
    "invoice": "ACM"
  },
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "object": "brand",
  "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "slug": "acme-app",
  "name": "Acme App",
  "status": "test_only",
  "isPlatformBrand": false,
  "branding": {
    "logoUrl": null,
    "iconUrl": null,
    "primaryColor": null,
    "accentColor": null,
    "supportEmail": null,
    "supportUrl": null,
    "termsUrl": null,
    "privacyUrl": null
  },
  "statementDescriptor": "ACME APP",
  "statementDescriptorSuffix": null,
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [1, 3, 5, 7],
      "finalAction": "unpaid"
    },
    "entitlementGraceDays": 7,
    "sendInvoice": {
      "graceDays": 14
    },
    "cardExpiryReminders": true,
    "pausedEntitlements": false,
    "paymentBehavior": "allow_incomplete"
  },
  "policies": {
    "breakageRecognition": "at_expiry",
    "supportRefundLimits": [],
    "disputeWalletFreeze": true,
    "taxIdUnavailable": "charge_as_b2c"
  },
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [],
    "allowCancel": true,
    "cancelBehavior": "period_end",
    "collectCancelReason": true,
    "allowQuantityChanges": false
  },
  "checkoutSettings": {
    "locales": ["en", "hr"],
    "collectPhone": false,
    "requireBusinessDetails": "auto"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T12:00:00.000Z"
}

With support and legal links

Arguments:

JSON
{
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "name": "Acme App",
  "slug": "acme-app",
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "statementDescriptor": "ACME APP",
  "branding": {
    "supportEmail": "help@acme.example",
    "termsUrl": "https://acme.example/terms",
    "privacyUrl": "https://acme.example/privacy"
  },
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "object": "brand",
  "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "slug": "acme-app",
  "name": "Acme App",
  "status": "test_only",
  "isPlatformBrand": false,
  "branding": {
    "logoUrl": null,
    "iconUrl": null,
    "primaryColor": null,
    "accentColor": null,
    "supportEmail": "help@acme.example",
    "supportUrl": null,
    "termsUrl": "https://acme.example/terms",
    "privacyUrl": "https://acme.example/privacy"
  },
  "statementDescriptor": "ACME APP",
  "statementDescriptorSuffix": null,
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [1, 3, 5, 7],
      "finalAction": "unpaid"
    },
    "entitlementGraceDays": 7,
    "sendInvoice": {
      "graceDays": 14
    },
    "cardExpiryReminders": true,
    "pausedEntitlements": false,
    "paymentBehavior": "allow_incomplete"
  },
  "policies": {
    "breakageRecognition": "at_expiry",
    "supportRefundLimits": [],
    "disputeWalletFreeze": true,
    "taxIdUnavailable": "charge_as_b2c"
  },
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [],
    "allowCancel": true,
    "cancelBehavior": "period_end",
    "collectCancelReason": true,
    "allowQuantityChanges": false
  },
  "checkoutSettings": {
    "locales": ["en", "hr"],
    "collectPhone": false,
    "requireBusinessDetails": "auto"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T12:00:00.000Z"
}

brands_domains_add

Add a custom domain to a brand. Operation brands.domains.add · Organization level · permission brands:write · risk tier write · since M9

Adds a custom domain on which the brand's hosted checkout (purpose: checkout) or customer portal (purpose: portal) is served, and attaches it to Ownrecord's hosting. The answer has the DNS records to create at your DNS provider:

  • a CNAME for a subdomain such as pay.acme.com (recommended), or A records for a domain at the apex;
  • a TXT record _ownrecord-challenge.{host} with the value ownrecord-verify={token}, which proves the domain is yours. The token is new for every domain added;
  • a TXT record of the hosting provider, when it needs its own proof because another account uses the domain.

The domain is pending until its DNS points at Ownrecord and the challenge record is in place; then brands.domains.verify marks it verified. From then on, checkout links of the brand (the session url, waitlist and invoice emails) use the domain, without the brand's slug: https://pay.acme.com/cs_….

A brand has at most one checkout and one portal domain, and a host belongs to one brand only. The plan limits the custom domains of the whole organization (custom_domains.max). Needs brands:write.

Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: false · openWorldHint: true

Arguments

ArgumentTypeRequiredDescription
idID (brd_…)yes–
hoststringyesThe host name, e.g. pay.acme.com: one you registered, without https:// or a path. (at most 300 characters)
purposeone of checkout, portalyescheckout serves the brand's hosted checkout, portal its customer portal.
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
idempotency_keystringnoA unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters)
dry_runbooleannotrue: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false)
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Idempotency: the result returns the idempotency_key used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
  • Dry run: supported. dry_run: true checks permissions and rules and computes the result, then rolls everything back.

Errors

Examples

A checkout domain

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "host": "pay.acme-app.com",
  "purpose": "checkout",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "object": "brand_domain",
  "host": "pay.acme-app.com",
  "purpose": "checkout",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "status": "pending",
  "verifiedAt": null,
  "url": "https://pay.acme-app.com",
  "dnsRecords": [
    {
      "type": "CNAME",
      "name": "pay.acme-app.com",
      "label": "pay",
      "value": "cname.vercel-dns.com",
      "purpose": "routing"
    },
    {
      "type": "TXT",
      "name": "_ownrecord-challenge.pay.acme-app.com",
      "label": "_ownrecord-challenge.pay",
      "value": "ownrecord-verify=5e0c9a1b7d3f42e8a6b0c4d2e9f17a35",
      "purpose": "ownership"
    }
  ],
  "check": {
    "checkedAt": "2026-10-20T09:00:00.000Z",
    "ownershipVerified": true,
    "dnsConfigured": false,
    "challengeVerified": false,
    "problems": [
      {
        "code": "dns_not_configured",
        "message": "The host doesn't point at Ownrecord yet. Create the DNS records below; changes can take up to a few hours."
      },
      {
        "code": "challenge_missing",
        "message": "Ownrecord can't find its _ownrecord-challenge TXT record yet. Create it with the value below to prove the domain is yours."
      }
    ],
    "simulated": false
  }
}

A portal domain whose hosting provider asks for its own TXT record too

The domain is used by another account at the hosting provider, which asks for proof of ownership as well.

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "host": "billing.acme-app.com",
  "purpose": "portal",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "object": "brand_domain",
  "host": "billing.acme-app.com",
  "purpose": "portal",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "status": "pending",
  "verifiedAt": null,
  "url": "https://billing.acme-app.com",
  "dnsRecords": [
    {
      "type": "CNAME",
      "name": "billing.acme-app.com",
      "label": "billing",
      "value": "cname.vercel-dns.com",
      "purpose": "routing"
    },
    {
      "type": "TXT",
      "name": "_ownrecord-challenge.billing.acme-app.com",
      "label": "_ownrecord-challenge.billing",
      "value": "ownrecord-verify=c18d7e2f90ab4c3d8e5f6a7b1c2d3e4f",
      "purpose": "ownership"
    },
    {
      "type": "TXT",
      "name": "_vercel.acme-app.com",
      "label": "_vercel",
      "value": "vc-domain-verify=billing.acme-app.com,9b1f6c2e8d3a4f5b6c7d",
      "purpose": "ownership"
    }
  ],
  "check": {
    "checkedAt": "2026-10-20T09:00:00.000Z",
    "ownershipVerified": false,
    "dnsConfigured": false,
    "challengeVerified": false,
    "problems": [
      {
        "code": "ownership_unverified",
        "message": "The domain is used elsewhere on the hosting platform. Add the TXT record below to prove it's yours."
      },
      {
        "code": "dns_not_configured",
        "message": "The host doesn't point at Ownrecord yet. Create the DNS records below; changes can take up to a few hours."
      },
      {
        "code": "challenge_missing",
        "message": "Ownrecord can't find its _ownrecord-challenge TXT record yet. Create it with the value below to prove the domain is yours."
      }
    ],
    "simulated": false
  }
}

brands_domains_list

List a brand's custom domains. Operation brands.domains.list · Organization level · permission brands:read · risk tier read · since M9

Lists the brand's custom domains (at most one for checkout and one for the customer portal) with their status and the DNS records to create, and how many custom domains the organization uses against its plan's limit (custom_domains.max, counted across all brands).

A pending domain doesn't serve anything yet; links keep using Ownrecord's own address until it is verified. The records shown here are the general ones; brands.domains.verify asks the domain provider again and returns the records it recommends for this domain, including a TXT record when it needs proof of ownership.

Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
idID (brd_…)yes–
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Read-only: changes nothing; idempotency_key is ignored.

Errors

Examples

A verified checkout domain

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4"
}

Result output:

JSON
{
  "object": "list",
  "data": [
    {
      "object": "brand_domain",
      "host": "pay.acme-app.com",
      "purpose": "checkout",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "status": "verified",
      "verifiedAt": "2026-10-20T09:40:00.000Z",
      "url": "https://pay.acme-app.com",
      "dnsRecords": [
        {
          "type": "CNAME",
          "name": "pay.acme-app.com",
          "label": "pay",
          "value": "cname.vercel-dns.com",
          "purpose": "routing"
        },
        {
          "type": "TXT",
          "name": "_ownrecord-challenge.pay.acme-app.com",
          "label": "_ownrecord-challenge.pay",
          "value": "ownrecord-verify=5e0c9a1b7d3f42e8a6b0c4d2e9f17a35",
          "purpose": "ownership"
        }
      ],
      "check": null
    }
  ],
  "usage": {
    "used": 1,
    "limit": 2
  }
}

A checkout domain waiting for its DNS record

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4"
}

Result output:

JSON
{
  "object": "list",
  "data": [
    {
      "object": "brand_domain",
      "host": "pay.acme-app.com",
      "purpose": "checkout",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "status": "pending",
      "verifiedAt": null,
      "url": "https://pay.acme-app.com",
      "dnsRecords": [
        {
          "type": "CNAME",
          "name": "pay.acme-app.com",
          "label": "pay",
          "value": "cname.vercel-dns.com",
          "purpose": "routing"
        },
        {
          "type": "TXT",
          "name": "_ownrecord-challenge.pay.acme-app.com",
          "label": "_ownrecord-challenge.pay",
          "value": "ownrecord-verify=5e0c9a1b7d3f42e8a6b0c4d2e9f17a35",
          "purpose": "ownership"
        }
      ],
      "check": null
    }
  ],
  "usage": {
    "used": 1,
    "limit": 2
  }
}

brands_domains_remove

Remove a custom domain from a brand. Operation brands.domains.remove · Organization level · permission brands:write · risk tier write · since M9

Removes one of the brand's custom domains. Its hosted pages stop being served on it within a minute, links sent earlier that use it stop working, and new links use Ownrecord's own address (or the brand's other verified domain). The domain is then detached from Ownrecord's hosting in the background.

The domain stops counting against the plan's custom_domains.max at once, and can be added again later, to this brand or another. Needs brands:write.

Annotations: readOnlyHint: false · destructiveHint: true · idempotentHint: false · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
idID (brd_…)yes–
hoststringyesThe domain's host name, e.g. pay.acme.com. (1–300 characters)
reasonstringnoWhy, for the audit log. (1–500 characters)
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
idempotency_keystringnoA unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters)
dry_runbooleannotrue: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false)
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Idempotency: the result returns the idempotency_key used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
  • Dry run: supported. dry_run: true checks permissions and rules and computes the result, then rolls everything back.

Errors

Example

Remove the checkout domain

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "host": "pay.acme-app.com",
  "reason": "Moving checkout to pay.acme.io",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "object": "brand_domain",
  "host": "pay.acme-app.com",
  "purpose": "checkout",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "deleted": true
}

brands_domains_verify

Check a custom domain again. Operation brands.domains.verify · Organization level · permission brands:write · risk tier write · since M9

Asks the domain provider to verify one of the brand's custom domains again, looks up the domain's _ownrecord-challenge TXT record, and records the answer: verified once the domain is attached, its DNS points at Ownrecord and the challenge record carries the domain's token (ownrecord-verify={token}); pending otherwise, with the records still needed in dnsRecords and what is missing in check.problems.

A verified domain that no longer passes, for example because the challenge record was deleted, goes back to pending: its pages stop being served and links stop using it until it is verified again. DNS changes can take a few hours to be seen; checking again is safe at any time.

Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: true

Arguments

ArgumentTypeRequiredDescription
idID (brd_…)yes–
hoststringyesThe domain's host name, e.g. pay.acme.com. (1–300 characters)
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
idempotency_keystringnoA unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters)
dry_runbooleannotrue: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false)
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Idempotency: the result returns the idempotency_key used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
  • Dry run: supported. dry_run: true checks permissions and rules and computes the result, then rolls everything back.

Errors

Examples

DNS points at Ownrecord and the challenge record is in place

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "host": "pay.acme-app.com",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "object": "brand_domain",
  "host": "pay.acme-app.com",
  "purpose": "checkout",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "status": "verified",
  "verifiedAt": "2026-10-20T09:40:00.000Z",
  "url": "https://pay.acme-app.com",
  "dnsRecords": [
    {
      "type": "CNAME",
      "name": "pay.acme-app.com",
      "label": "pay",
      "value": "cname.vercel-dns.com",
      "purpose": "routing"
    },
    {
      "type": "TXT",
      "name": "_ownrecord-challenge.pay.acme-app.com",
      "label": "_ownrecord-challenge.pay",
      "value": "ownrecord-verify=5e0c9a1b7d3f42e8a6b0c4d2e9f17a35",
      "purpose": "ownership"
    }
  ],
  "check": {
    "checkedAt": "2026-10-20T09:40:00.000Z",
    "ownershipVerified": true,
    "dnsConfigured": true,
    "challengeVerified": true,
    "problems": [],
    "simulated": false
  }
}

Still waiting for the DNS records

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "host": "pay.acme-app.com",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "object": "brand_domain",
  "host": "pay.acme-app.com",
  "purpose": "checkout",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "status": "pending",
  "verifiedAt": null,
  "url": "https://pay.acme-app.com",
  "dnsRecords": [
    {
      "type": "CNAME",
      "name": "pay.acme-app.com",
      "label": "pay",
      "value": "cname.vercel-dns.com",
      "purpose": "routing"
    },
    {
      "type": "TXT",
      "name": "_ownrecord-challenge.pay.acme-app.com",
      "label": "_ownrecord-challenge.pay",
      "value": "ownrecord-verify=5e0c9a1b7d3f42e8a6b0c4d2e9f17a35",
      "purpose": "ownership"
    }
  ],
  "check": {
    "checkedAt": "2026-10-20T09:00:00.000Z",
    "ownershipVerified": true,
    "dnsConfigured": false,
    "challengeVerified": false,
    "problems": [
      {
        "code": "dns_not_configured",
        "message": "The host doesn't point at Ownrecord yet. Create the DNS records below; changes can take up to a few hours."
      },
      {
        "code": "challenge_missing",
        "message": "Ownrecord can't find its _ownrecord-challenge TXT record yet. Create it with the value below to prove the domain is yours."
      }
    ],
    "simulated": false
  }
}

brands_get

Get a brand. Operation brands.get · Organization level · permission brands:read · risk tier read · since M1

Returns one brand by its ID (brd_…): name, slug, status, branding, statement descriptor and invoice series. A brand outside the request's scope (another organization, another entity of an entity-scoped request, or a sibling of a brand-scoped one) is resource_not_found.

Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
idID (brd_…)yes–
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Read-only: changes nothing; idempotency_key is ignored.

Errors

Example

Read a brand

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4"
}

Result output:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "object": "brand",
  "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "slug": "acme-app",
  "name": "Acme App",
  "status": "test_only",
  "isPlatformBrand": false,
  "branding": {
    "logoUrl": null,
    "iconUrl": null,
    "primaryColor": null,
    "accentColor": null,
    "supportEmail": null,
    "supportUrl": null,
    "termsUrl": null,
    "privacyUrl": null
  },
  "statementDescriptor": "ACME APP",
  "statementDescriptorSuffix": null,
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [1, 3, 5, 7],
      "finalAction": "unpaid"
    },
    "entitlementGraceDays": 7,
    "sendInvoice": {
      "graceDays": 14
    },
    "cardExpiryReminders": true,
    "pausedEntitlements": false,
    "paymentBehavior": "allow_incomplete"
  },
  "policies": {
    "breakageRecognition": "at_expiry",
    "supportRefundLimits": [],
    "disputeWalletFreeze": true,
    "taxIdUnavailable": "charge_as_b2c"
  },
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [],
    "allowCancel": true,
    "cancelBehavior": "period_end",
    "collectCancelReason": true,
    "allowQuantityChanges": false
  },
  "checkoutSettings": {
    "locales": ["en", "hr"],
    "collectPhone": false,
    "requireBusinessDetails": "auto"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T12:00:00.000Z"
}

brands_go_live

Take a brand live. Operation brands.go_live · Organization level · permission brands:admin · risk tier security · since M12

Moves the brand from test mode (test_only) to live, so it can take real payments, once every item of its go-live checklist holds (brands.go_live_checklist). The brand's live processor connection is tested at the processor first, and the test result is recorded on the connection. If anything is missing the call fails with go_live_requirements_unmet and details.unmet lists what. A brand that is live already is returned as is.

After this, live API keys can be created for the brand and its live checkout sessions are accepted.

Call it in live mode, with a sign-in in the last 15 minutes in the console. Security tier for agents (it needs approval). Needs brands:admin (organization owners and admins).

Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: true

Arguments

ArgumentTypeRequiredDescription
idID (brd_…)yes–
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
idempotency_keystringnoA unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters)
dry_runbooleannotrue: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false)
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Idempotency: the result returns the idempotency_key used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
  • Dry run: supported. dry_run: true checks permissions and rules and computes the result, then rolls everything back.
  • Mode: live-mode keys only.

Errors

Example

Every item holds

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "brand": {
    "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
    "object": "brand",
    "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
    "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
    "slug": "acme-app",
    "name": "Acme App",
    "status": "live",
    "isPlatformBrand": false,
    "branding": {
      "logoUrl": null,
      "iconUrl": null,
      "primaryColor": null,
      "accentColor": null,
      "supportEmail": null,
      "supportUrl": null,
      "termsUrl": null,
      "privacyUrl": null
    },
    "statementDescriptor": "ACME APP",
    "statementDescriptorSuffix": null,
    "invoiceSeries": {
      "invoice": "ACM",
      "creditNote": "ACM-CN"
    },
    "billingSettings": {
      "dunning": {
        "retryOffsetsDays": [1, 3, 5, 7],
        "finalAction": "unpaid"
      },
      "entitlementGraceDays": 7,
      "sendInvoice": {
        "graceDays": 14
      },
      "cardExpiryReminders": true,
      "pausedEntitlements": false,
      "paymentBehavior": "allow_incomplete"
    },
    "policies": {
      "breakageRecognition": "at_expiry",
      "supportRefundLimits": [],
      "disputeWalletFreeze": true,
      "taxIdUnavailable": "charge_as_b2c"
    },
    "portalSettings": {
      "allowPlanChanges": true,
      "planChangeMatrix": [],
      "allowCancel": true,
      "cancelBehavior": "period_end",
      "collectCancelReason": true,
      "allowQuantityChanges": false
    },
    "checkoutSettings": {
      "locales": ["en", "hr"],
      "collectPhone": false,
      "requireBusinessDetails": "auto"
    },
    "createdAt": "2026-10-13T12:00:00.000Z",
    "updatedAt": "2026-10-13T12:00:00.000Z"
  },
  "checklist": {
    "object": "go_live_checklist",
    "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
    "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
    "brandStatus": "live",
    "ready": true,
    "live": true,
    "items": [
      {
        "requirement": "plan_livemode",
        "met": true,
        "reason": null
      },
      {
        "requirement": "org_status",
        "met": true,
        "reason": null
      },
      {
        "requirement": "legal_accepted",
        "met": true,
        "reason": null
      },
      {
        "requirement": "entity_verified",
        "met": true,
        "reason": null
      },
      {
        "requirement": "invoice_settings",
        "met": true,
        "reason": null
      },
      {
        "requirement": "home_registration",
        "met": true,
        "reason": null
      },
      {
        "requirement": "processor_live",
        "met": true,
        "reason": null
      },
      {
        "requirement": "brand_urls",
        "met": true,
        "reason": null
      },
      {
        "requirement": "brand_status",
        "met": true,
        "reason": null
      }
    ],
    "processor": {
      "connectionId": "pcon_01m4tx5nj8emwbyf7y9vcf47xd",
      "processor": "stripe",
      "status": "active",
      "lastTestOk": true,
      "lastTestAt": "2026-10-26T09:00:00.000Z"
    },
    "legalVersions": {
      "terms": "1.0",
      "dpa": "1.0"
    },
    "legalAccepted": {
      "terms": true,
      "dpa": false
    }
  }
}

brands_go_live_checklist

Get a brand's go-live checklist. Operation brands.go_live_checklist · Organization level · permission brands:read · risk tier read · since M12

Returns what the brand needs before it can go live, each requirement met or not with the reason:

  • plan_livemode: the organization's plan includes live mode;
  • org_status: the organization is active (not restricted, suspended, closing or closed);
  • legal_accepted: the current Terms of Service and Data Processing Agreement are accepted;
  • entity_verified: the legal entity's tax ID is verified;
  • invoice_settings: the entity's invoice details are complete;
  • home_registration: the entity's home registration is registered, with a number (live mode);
  • processor_live: the brand has a live processor connection whose last connection test passed (going live tests it again);
  • brand_urls: the brand has its terms and privacy URLs;
  • brand_status: the brand is in test mode (test_only), not suspended.

Live API keys and live checkout sessions are refused until the brand is live. Reading the checklist calls no processor.

Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
idID (brd_…)yes–
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Read-only: changes nothing; idempotency_key is ignored.

Errors

Example

Two items left

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4"
}

Result output:

JSON
{
  "object": "go_live_checklist",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "brandStatus": "test_only",
  "ready": false,
  "live": false,
  "items": [
    {
      "requirement": "plan_livemode",
      "met": true,
      "reason": null
    },
    {
      "requirement": "org_status",
      "met": true,
      "reason": null
    },
    {
      "requirement": "legal_accepted",
      "met": false,
      "reason": "An owner or admin must accept the current version of the Data Processing Agreement."
    },
    {
      "requirement": "entity_verified",
      "met": true,
      "reason": null
    },
    {
      "requirement": "invoice_settings",
      "met": true,
      "reason": null
    },
    {
      "requirement": "home_registration",
      "met": true,
      "reason": null
    },
    {
      "requirement": "processor_live",
      "met": true,
      "reason": null
    },
    {
      "requirement": "brand_urls",
      "met": false,
      "reason": "The brand needs its privacy URL."
    },
    {
      "requirement": "brand_status",
      "met": true,
      "reason": null
    }
  ],
  "processor": {
    "connectionId": "pcon_01m4tx5nj8emwbyf7y9vcf47xd",
    "processor": "stripe",
    "status": "active",
    "lastTestOk": true,
    "lastTestAt": "2026-10-26T09:00:00.000Z"
  },
  "legalVersions": {
    "terms": "1.0",
    "dpa": "1.0"
  },
  "legalAccepted": {
    "terms": true,
    "dpa": false
  }
}

brands_list

List brands. Operation brands.list · Organization level · permission brands:read · risk tier read · since M1

Lists brands, newest first. What a request sees depends on its scope: an organization-level request every brand of every entity (filter with entityId), a request inside one entity all of that entity's brands, and a request inside one brand only that brand.

Paginate with limit (1–100, default 10) and starting_after (the next_cursor of the previous page).

Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
entityIdID (ent_…)no–
limitintegerno(1–100)
starting_afterID (brd_…)no–
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Read-only: changes nothing; idempotency_key is ignored.

Errors

Example

Every brand of one entity

Arguments:

JSON
{
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2"
}

Result output:

JSON
{
  "object": "list",
  "data": [
    {
      "id": "brd_01m4tx5nj8emwbyf7y9vcf47x5",
      "object": "brand",
      "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "slug": "acme-labs",
      "name": "Acme Labs",
      "status": "test_only",
      "isPlatformBrand": false,
      "branding": {
        "logoUrl": null,
        "iconUrl": null,
        "primaryColor": null,
        "accentColor": null,
        "supportEmail": null,
        "supportUrl": null,
        "termsUrl": null,
        "privacyUrl": null
      },
      "statementDescriptor": "ACME APP",
      "statementDescriptorSuffix": null,
      "invoiceSeries": {
        "invoice": "LAB",
        "creditNote": "LAB-CN"
      },
      "billingSettings": {
        "dunning": {
          "retryOffsetsDays": [1, 3, 5, 7],
          "finalAction": "unpaid"
        },
        "entitlementGraceDays": 7,
        "sendInvoice": {
          "graceDays": 14
        },
        "cardExpiryReminders": true,
        "pausedEntitlements": false,
        "paymentBehavior": "allow_incomplete"
      },
      "policies": {
        "breakageRecognition": "at_expiry",
        "supportRefundLimits": [],
        "disputeWalletFreeze": true,
        "taxIdUnavailable": "charge_as_b2c"
      },
      "portalSettings": {
        "allowPlanChanges": true,
        "planChangeMatrix": [],
        "allowCancel": true,
        "cancelBehavior": "period_end",
        "collectCancelReason": true,
        "allowQuantityChanges": false
      },
      "checkoutSettings": {
        "locales": ["en", "hr"],
        "collectPhone": false,
        "requireBusinessDetails": "auto"
      },
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-13T12:00:00.000Z"
    },
    {
      "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "object": "brand",
      "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "slug": "acme-app",
      "name": "Acme App",
      "status": "test_only",
      "isPlatformBrand": false,
      "branding": {
        "logoUrl": null,
        "iconUrl": null,
        "primaryColor": null,
        "accentColor": null,
        "supportEmail": null,
        "supportUrl": null,
        "termsUrl": null,
        "privacyUrl": null
      },
      "statementDescriptor": "ACME APP",
      "statementDescriptorSuffix": null,
      "invoiceSeries": {
        "invoice": "ACM",
        "creditNote": "ACM-CN"
      },
      "billingSettings": {
        "dunning": {
          "retryOffsetsDays": [1, 3, 5, 7],
          "finalAction": "unpaid"
        },
        "entitlementGraceDays": 7,
        "sendInvoice": {
          "graceDays": 14
        },
        "cardExpiryReminders": true,
        "pausedEntitlements": false,
        "paymentBehavior": "allow_incomplete"
      },
      "policies": {
        "breakageRecognition": "at_expiry",
        "supportRefundLimits": [],
        "disputeWalletFreeze": true,
        "taxIdUnavailable": "charge_as_b2c"
      },
      "portalSettings": {
        "allowPlanChanges": true,
        "planChangeMatrix": [],
        "allowCancel": true,
        "cancelBehavior": "period_end",
        "collectCancelReason": true,
        "allowQuantityChanges": false
      },
      "checkoutSettings": {
        "locales": ["en", "hr"],
        "collectPhone": false,
        "requireBusinessDetails": "auto"
      },
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

brands_update

Update a brand. Operation brands.update · Organization level · permission brands:write · risk tier write · since M1

Renames a brand or changes its slug, branding (logo, icon, colors, support email and URL, terms and privacy URLs), statement descriptor or billing settings. Send only the fields to change; null clears an optional value (for a billing setting: back to its default).

Billing settings: dunning.retryOffsetsDays (retries after a failed charge, days after the first failure, default 1, 3, 5, 7), dunning.finalAction (unpaid, the default, or canceled after the last retry), entitlementGraceDays (features stay on while past due, default 7), sendInvoice.graceDays (a send_invoice invoice is overdue this many days after its due date, default 14), cardExpiryReminders (default on), pausedEntitlements (paused subscriptions keep their features, default off) and paymentBehavior (default for immediate changes invoiced to a card). They apply from the next step of each subscription.

Policies: breakageRecognition says when expired paid credits become breakage revenue: at_expiry (the default) or manual, which holds them as expired credits until your finance team recognises them with a ledger adjustment. It applies to credits that expire from then on. disputeWalletFreeze (default on) freezes the customer's wallets when a dispute opens; a won dispute unfreezes the wallets it froze. supportRefundLimits sets the most the support role may refund at once, per currency (100 of a currency without one; finance has no limit). taxIdUnavailable says what a sale does when a business customer's tax ID couldn't be checked because the register didn't answer (spec §9.1): charge_as_b2c (the default: tax is charged as for a consumer, and a credit note can refund it once the ID validates) or block (the sale is refused with tax_id_unavailable until the register answers). It applies to quotes from then on.

Customer portal (portalSettings): whether customers may switch plans (allowPlanChanges, along planChangeMatrix: one row per price naming the prices it may switch to, in the same mode and currency; no row means no switch), cancel (allowCancel, cancelBehavior period_end or immediate, collectCancelReason) and change seats (allowQuantityChanges). The matrix is checked against the brand's prices and replaced whole.

Languages (checkoutSettings.locales): the brand's languages for hosted pages and customer emails, its default first. A customer's own language and their browser's come first; the brand's default is the fallback.

A new slug changes the brand's checkout URLs; existing API keys keep working. The invoice series can't change once set. Needs brands:write (organization owners and admins, or an API key with that scope).

Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
idID (brd_…)yes–
namestringno(1–120 characters)
slugstringno(3–40 characters)
brandingobjectno–
statementDescriptorstringno(5–22 characters)
statementDescriptorSuffixstring or nullno–
billingSettingsobjectnoBilling settings; each field: a value sets it, null resets it to the default, absent leaves it.
policiesobjectnoAccounting policies; each field: a value sets it, null resets it to the default, absent leaves it.
portalSettingsobjectnoThe customer portal's settings; send only what changes.
checkoutSettingsobjectnoHosted page settings; send only what changes.
entity_idID (ent_…)noOptional: act inside this legal entity (ent_…) instead of the whole organization.
brand_idID (brd_…)noOptional: act inside this brand (brd_…) instead of the whole organization.
idempotency_keystringnoA unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters)
dry_runbooleannotrue: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false)
  • Scope: the whole organization, or one legal entity or brand of it with entity_id or brand_id.
  • Idempotency: the result returns the idempotency_key used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
  • Dry run: supported. dry_run: true checks permissions and rules and computes the result, then rolls everything back.

Errors

  • validation_failed: No field to change was sent, or one is malformed; or a plan-change matrix row names a price that isn't the brand's recurring licensed price, an archived target, or a target in another mode or currency (details.issues).
  • slug_invalid: The slug has the wrong format or is a reserved word.
  • slug_taken: Another brand already uses this slug.
  • resource_not_found: No brand with this ID is visible to the request.
  • version_conflict: The brand changed at the same time; retry.
  • permission_denied: You can't change brands here.

Examples

Set the support email and legal links

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "branding": {
    "supportEmail": "help@acme.example",
    "termsUrl": "https://acme.example/terms",
    "privacyUrl": "https://acme.example/privacy"
  },
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "object": "brand",
  "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "slug": "acme-app",
  "name": "Acme App",
  "status": "test_only",
  "isPlatformBrand": false,
  "branding": {
    "logoUrl": null,
    "iconUrl": null,
    "primaryColor": null,
    "accentColor": null,
    "supportEmail": "help@acme.example",
    "supportUrl": null,
    "termsUrl": "https://acme.example/terms",
    "privacyUrl": "https://acme.example/privacy"
  },
  "statementDescriptor": "ACME APP",
  "statementDescriptorSuffix": null,
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [1, 3, 5, 7],
      "finalAction": "unpaid"
    },
    "entitlementGraceDays": 7,
    "sendInvoice": {
      "graceDays": 14
    },
    "cardExpiryReminders": true,
    "pausedEntitlements": false,
    "paymentBehavior": "allow_incomplete"
  },
  "policies": {
    "breakageRecognition": "at_expiry",
    "supportRefundLimits": [],
    "disputeWalletFreeze": true,
    "taxIdUnavailable": "charge_as_b2c"
  },
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [],
    "allowCancel": true,
    "cancelBehavior": "period_end",
    "collectCancelReason": true,
    "allowQuantityChanges": false
  },
  "checkoutSettings": {
    "locales": ["en", "hr"],
    "collectPhone": false,
    "requireBusinessDetails": "auto"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z"
}

Cancel after the last of three retries

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [2, 4, 7],
      "finalAction": "canceled"
    }
  },
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "object": "brand",
  "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "slug": "acme-app",
  "name": "Acme App",
  "status": "test_only",
  "isPlatformBrand": false,
  "branding": {
    "logoUrl": null,
    "iconUrl": null,
    "primaryColor": null,
    "accentColor": null,
    "supportEmail": null,
    "supportUrl": null,
    "termsUrl": null,
    "privacyUrl": null
  },
  "statementDescriptor": "ACME APP",
  "statementDescriptorSuffix": null,
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [2, 4, 7],
      "finalAction": "canceled"
    },
    "entitlementGraceDays": 7,
    "sendInvoice": {
      "graceDays": 14
    },
    "cardExpiryReminders": true,
    "pausedEntitlements": false,
    "paymentBehavior": "allow_incomplete"
  },
  "policies": {
    "breakageRecognition": "at_expiry",
    "supportRefundLimits": [],
    "disputeWalletFreeze": true,
    "taxIdUnavailable": "charge_as_b2c"
  },
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [],
    "allowCancel": true,
    "cancelBehavior": "period_end",
    "collectCancelReason": true,
    "allowQuantityChanges": false
  },
  "checkoutSettings": {
    "locales": ["en", "hr"],
    "collectPhone": false,
    "requireBusinessDetails": "auto"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z"
}

Hold expired credits until finance recognises the breakage

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "policies": {
    "breakageRecognition": "manual"
  },
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "object": "brand",
  "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "slug": "acme-app",
  "name": "Acme App",
  "status": "test_only",
  "isPlatformBrand": false,
  "branding": {
    "logoUrl": null,
    "iconUrl": null,
    "primaryColor": null,
    "accentColor": null,
    "supportEmail": null,
    "supportUrl": null,
    "termsUrl": null,
    "privacyUrl": null
  },
  "statementDescriptor": "ACME APP",
  "statementDescriptorSuffix": null,
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [1, 3, 5, 7],
      "finalAction": "unpaid"
    },
    "entitlementGraceDays": 7,
    "sendInvoice": {
      "graceDays": 14
    },
    "cardExpiryReminders": true,
    "pausedEntitlements": false,
    "paymentBehavior": "allow_incomplete"
  },
  "policies": {
    "breakageRecognition": "manual",
    "supportRefundLimits": [],
    "disputeWalletFreeze": true,
    "taxIdUnavailable": "charge_as_b2c"
  },
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [],
    "allowCancel": true,
    "cancelBehavior": "period_end",
    "collectCancelReason": true,
    "allowQuantityChanges": false
  },
  "checkoutSettings": {
    "locales": ["en", "hr"],
    "collectPhone": false,
    "requireBusinessDetails": "auto"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z"
}

Refuse sales while a business customer's tax ID can't be checked

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "policies": {
    "taxIdUnavailable": "block"
  },
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "object": "brand",
  "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "slug": "acme-app",
  "name": "Acme App",
  "status": "test_only",
  "isPlatformBrand": false,
  "branding": {
    "logoUrl": null,
    "iconUrl": null,
    "primaryColor": null,
    "accentColor": null,
    "supportEmail": null,
    "supportUrl": null,
    "termsUrl": null,
    "privacyUrl": null
  },
  "statementDescriptor": "ACME APP",
  "statementDescriptorSuffix": null,
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [1, 3, 5, 7],
      "finalAction": "unpaid"
    },
    "entitlementGraceDays": 7,
    "sendInvoice": {
      "graceDays": 14
    },
    "cardExpiryReminders": true,
    "pausedEntitlements": false,
    "paymentBehavior": "allow_incomplete"
  },
  "policies": {
    "breakageRecognition": "at_expiry",
    "supportRefundLimits": [],
    "disputeWalletFreeze": true,
    "taxIdUnavailable": "block"
  },
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [],
    "allowCancel": true,
    "cancelBehavior": "period_end",
    "collectCancelReason": true,
    "allowQuantityChanges": false
  },
  "checkoutSettings": {
    "locales": ["en", "hr"],
    "collectPhone": false,
    "requireBusinessDetails": "auto"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z"
}

Let support refund up to €250 at once

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "policies": {
    "supportRefundLimits": [
      {
        "amount": "250000000",
        "currency": "EUR"
      }
    ]
  },
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "object": "brand",
  "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "slug": "acme-app",
  "name": "Acme App",
  "status": "test_only",
  "isPlatformBrand": false,
  "branding": {
    "logoUrl": null,
    "iconUrl": null,
    "primaryColor": null,
    "accentColor": null,
    "supportEmail": null,
    "supportUrl": null,
    "termsUrl": null,
    "privacyUrl": null
  },
  "statementDescriptor": "ACME APP",
  "statementDescriptorSuffix": null,
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [1, 3, 5, 7],
      "finalAction": "unpaid"
    },
    "entitlementGraceDays": 7,
    "sendInvoice": {
      "graceDays": 14
    },
    "cardExpiryReminders": true,
    "pausedEntitlements": false,
    "paymentBehavior": "allow_incomplete"
  },
  "policies": {
    "breakageRecognition": "at_expiry",
    "supportRefundLimits": [
      {
        "amount": "250000000",
        "currency": "EUR"
      }
    ],
    "disputeWalletFreeze": true,
    "taxIdUnavailable": "charge_as_b2c"
  },
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [],
    "allowCancel": true,
    "cancelBehavior": "period_end",
    "collectCancelReason": true,
    "allowQuantityChanges": false
  },
  "checkoutSettings": {
    "locales": ["en", "hr"],
    "collectPhone": false,
    "requireBusinessDetails": "auto"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z"
}

Let customers switch between Basic and Pro in the portal

Arguments:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [
      {
        "fromPriceId": "price_01m4tx5nj8emwbyf7y9vcf47xc",
        "toPriceIds": ["price_01m4tx5nj8emwbyf7y9vcf47xd"]
      },
      {
        "fromPriceId": "price_01m4tx5nj8emwbyf7y9vcf47xd",
        "toPriceIds": ["price_01m4tx5nj8emwbyf7y9vcf47xc"]
      }
    ],
    "collectCancelReason": true
  },
  "checkoutSettings": {
    "locales": ["de", "en"]
  },
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "object": "brand",
  "orgId": "org_01m4tx5nj7ekd958x53w4bntcg",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "slug": "acme-app",
  "name": "Acme App",
  "status": "test_only",
  "isPlatformBrand": false,
  "branding": {
    "logoUrl": null,
    "iconUrl": null,
    "primaryColor": null,
    "accentColor": null,
    "supportEmail": null,
    "supportUrl": null,
    "termsUrl": null,
    "privacyUrl": null
  },
  "statementDescriptor": "ACME APP",
  "statementDescriptorSuffix": null,
  "invoiceSeries": {
    "invoice": "ACM",
    "creditNote": "ACM-CN"
  },
  "billingSettings": {
    "dunning": {
      "retryOffsetsDays": [1, 3, 5, 7],
      "finalAction": "unpaid"
    },
    "entitlementGraceDays": 7,
    "sendInvoice": {
      "graceDays": 14
    },
    "cardExpiryReminders": true,
    "pausedEntitlements": false,
    "paymentBehavior": "allow_incomplete"
  },
  "policies": {
    "breakageRecognition": "at_expiry",
    "supportRefundLimits": [],
    "disputeWalletFreeze": true,
    "taxIdUnavailable": "charge_as_b2c"
  },
  "portalSettings": {
    "allowPlanChanges": true,
    "planChangeMatrix": [
      {
        "fromPriceId": "price_01m4tx5nj8emwbyf7y9vcf47xc",
        "toPriceIds": ["price_01m4tx5nj8emwbyf7y9vcf47xd"]
      },
      {
        "fromPriceId": "price_01m4tx5nj8emwbyf7y9vcf47xd",
        "toPriceIds": ["price_01m4tx5nj8emwbyf7y9vcf47xc"]
      }
    ],
    "allowCancel": true,
    "cancelBehavior": "period_end",
    "collectCancelReason": true,
    "allowQuantityChanges": false
  },
  "checkoutSettings": {
    "locales": ["de", "en"],
    "collectPhone": false,
    "requireBusinessDetails": "auto"
  },
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z"
}