---
title: "Client accounts under your brand"
url: /trust/clients
---

# Client accounts under your brand

> For an agency or studio: products built for clients on their own Stripe, sold under the agency's own brand and console, and handed over at the end.

A client account holds the products an agency builds for one client, on the client's own Stripe, behind a console that carries the agency's brand.

**A client account, opened to handed over.** ClientAccount.create.

1. Invited: its owner asked. Or expired: after 14 days.
2. Open (Stripe connected): its own Stripe.
3. Building (a product deployed): your team ships.
4. Handed off (the owner accepts): kept or moved. Or moved: to the client.
5. Closed (nothing left): records kept.

## What each client may do
`ClientAccount.grant` sets what a client's people may do. Each grant holds the ones above it in this table.

| Grant | A client's person may | Typical for |
| --- | --- | --- |
| `read` | See its products, usage, Customers and a statement per period | Every client |
| `prices` | Change the Offer's prices and plans, which deploy as a reviewed change | A client that runs its own pricing |
| `deploy` | Deploy a change your team prepared, after its review | A client with its own developer |
| `own` | Accept the product, which moves it to its own workspace | The end of an engagement |

A client never sees another client, your other products or your workspace's plan. Your team sees every client. Every act a client's person takes in the [client console](/trust/clients.md) is a Verb on the [platform API](/trust/planes.md), open to its agents under their own token.

## The console under your brand
`Workspace.brand` sets one brand for every client console and every email it sends, on Team and Scale.

| Part | Set by | What a client's people see |
| --- | --- | --- |
| Name, logo and colour | `name`, `logo`, `color` | Your mark on every screen, receipt and email; nothing names APIs.Dev |
| The address | `domain`, one of your [Domains](/reference/platform.md#host) | `console.yourstudio.com`, checked once by one DNS record |
| Sign-in | Your Domain's sign-in, with passkeys and SSO | A sign-in page and its emails from you |
| Sending | `from`, an address on your Domain | Invitations, statements and alerts from that address |
| Help | `support`, an address or a URL | Your own help, never the platform's |

## When a request is refused
Each refusal is a [Problem](/reference.md#errors) with its cure, and changes nothing that serves.

| What happens | The answer |
| --- | --- |
| Your team opens a client account past what the plan includes | 402 [`client_limit`](/reference.md#client_limit), with an add-on in `offers` |
| A product of a client goes Live, or charges, before the client connects Stripe | 409 [`stripe_not_connected`](/reference.md#stripe_not_connected); it keeps serving in Test |
| A client's person deploys, or changes prices, above the account's grant | 403 [`grant_exceeded`](/reference.md#grant_exceeded), naming the grant it needs |
| Anyone deploys or reprices a product whose handoff waits | 409 [`handoff_open`](/reference.md#handoff_open), with the handoff's link |
| The owner never accepts the invitation | The account turns `expired` after 14 days; `ClientAccount.invite` sends a new one |
| Your workspace drops below Team | Each console turns read-only and no account opens; every client keeps its Stripe and its Customers |

A client's Customers never meet any of these. Its products keep serving whatever the account's state.

## A studio and its first client
A studio brands its console, then opens an account for a client with a read grant for its finance lead.

```json title="Body"
{
  "brand": {
    "name": "Northwind Studio",
    "logo": "https://northwind.example.com/logo.svg",
    "color": "#1F5FBF",
    "domain": "console.northwind.example.com",
    "from": "clients@northwind.example.com",
    "support": "help@northwind.example.com"
  },
  "client": { "name": "Globex", "owner": "finance@globex.com", "grant": "read" }
}
```

```http title="Response"
HTTP/1.1 201 Created
Content-Type: application/json
X-Cost: price=0, currency="USD"
X-Request-Id: req_b9e04d27a3c1f85e6d02

{
  "id": "cla_7",
  "client": "Globex",
  "state": "invited",
  "console": "https://console.northwind.example.com/globex",
  "grant": "read",
  "stripe": "connect_pending",
  "expires": "2026-11-11T10:00:00Z"
}
```

That is `PUT https://apis.dev/v1/workspace/brand`, then `POST https://apis.dev/v1/client-accounts`.

## Numbers, statements and handoff
| What | How many, or how long |
| --- | --- |
| Client accounts | 10 with Team and 25 with Scale; each past them is an add-on on [/pricing](/pricing.md) |
| People in one client account | 50, one of them its owner |
| An invitation | 14 days, then `expired` |
| A logo | SVG or PNG, 200 KB at most |
| A handoff | Waits 30 days for the owner, then lapses and the product stays where it was |

Each client gets a statement per period in your name: its products' usage, revenue and the platform's charges.

A handoff ends the build. Kept, the product stays in your workspace and the client keeps its console. Moved, it goes to the client's workspace by [transfer](/lifecycle.md#end), and nothing its Customers see changes.