Customer accounts
Where your buyers go after they pay.
Every buyer who pays you needs somewhere to find an order, track a parcel, change a card, pause a subscription, or start a return. Flint ships that on day one, under your brand if you want it, on your own domain if you want that, and out of your way entirely if you would rather build it yourself. Those are three independent settings and one API, not four products. You can move between them without a rewrite.
On day one
A working account, and every link in Flint's email already pointing at it.
On your domain
Two DNS records. Flint provisions the certificate and serves the account.
Or your own
44 endpoints under /v1/me, authorized by a credential scoped to one buyer.
01The choice
It is a dial, not a fork.
Most platforms sell you a portal you cannot brand or an API and good luck. These are four positions on one setting, and only the last is a build.
| What the buyer sees | Where | What it costs you |
|---|---|---|
| Flint's account, Flint's brand | account.withflintpay.com | Nothing. It is already on. |
| Your colors, your name, no Flint mark | account.withflintpay.com | One settings call. |
| The same account, your address | account.yourbrand.com | One settings call and two DNS records. |
| Your account, your code | yourbrand.com/account | You build the UI on /v1/me. |
The reason this matters is the middle. A merchant who asks for a white-labeled buyer account usually means row three: their brand, their address, and none of their engineering time. Offering only the first row and the last one sends that merchant into a rebuild for what a domain and a logo would have solved.
Nothing here is a migration. The account is the same renderer at every row. Moving up is a settings call, and moving back is the same call with a different value.
02Your brand
Your colors, your name, no Flint mark.
Branding applies to the account, hosted checkout, and transactional email together, because a buyer meets all three and they should not look like three companies.
curl -X PATCH https://api.withflintpay.com/v1/settings \
-H "Authorization: Bearer $FLINT_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"branding": {
"primary_color": "#1B4D3E",
"background_color": "#F4EFE5",
"text_color": "#1A1714",
"font_family": "system_serif",
"corner_radius": 4
},
"customer_account": {
"mode": "flint_hosted",
"presentation": {
"account_name": "Cedar & Stone",
"is_flint_branding_hidden": true
}
}
}'Colors, type, and corner radius, plus the account name and Flint's mark switched off.
- primary_color
- background_color
- text_color
- font_family
- corner_radius
Four typefaces, six colors, and a radius. Deep enough to look like you, shallow enough that Flint can keep shipping the account without breaking your theme. Customer accounts guide →
03Your domain
account.yourbrand.com, certificate included.
The part every vendor demos and nobody explains: what happens to a live buyer link when DNS is wrong.
curl -X PATCH https://api.withflintpay.com/v1/settings \
-H "Authorization: Bearer $FLINT_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_account": {
"mode": "flint_hosted",
"presentation": { "custom_domain": "account.cedarandstone.com" }
}
}'It has to be a domain you already validated for payments, which is how Flint knows it is yours.
{
"data": {
"customer_account_domain_status": {
"hostname": "account.cedarandstone.com",
"domain_status": "provisioning",
"dns_records": [
{
"dns_record_type": "cname",
"name": "account.cedarandstone.com",
"value": "account.withflintpay.com"
},
{
"dns_record_type": "txt",
"name": "_acme-challenge.account.cedarandstone.com",
"value": "example-validation-token"
}
],
"last_checked_at": "2026-08-10T17:00:00Z"
}
}
}Flint returns exactly what to publish. Do not guess these, and do not hardcode them.
Provisioning
Records are published and the certificate is being issued. Links stay on Flint's domain meanwhile.
Active
Buyers land on your hostname. Nothing else about the account changed.
Attention required
A record is missing or wrong. Re-read the records rather than assuming which one moved.
An unhealthy domain never breaks a link. Flint re-checks the hostname on a schedule, and while it is anything other than active, every account link resolves to Flint's own origin instead. A buyer clicking a receipt from three weeks ago still reaches their order. What you lose is the branded address, not the account.
04Or build it
A credential scoped to one buyer.
Building the account yourself normally means reimplementing ownership checks and getting them wrong. This is the part Flint keeps.
curl -X POST https://api.withflintpay.com/v1/customer-sessions \
-H "Authorization: Bearer $FLINT_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{ "customer_id": "cus_1kmn0aExample" }'Your backend authenticates the buyer however it already does. Flint never sees your login.
{
"data": {
"customer_session_id": "cses_1kmn0aExample",
"customer_id": "cus_1kmn0aExample",
"secret": "flint_cses_example",
"expires_at": "2026-08-10T18:00:00Z",
"refresh_token": "flint_cref_example",
"refresh_token_expires_at": "2026-08-17T17:00:00Z"
}
}A working secret and a rotating refresh token. Both stay on your server.
curl https://api.withflintpay.com/v1/me/orders \
-H "Authorization: Bearer flint_cses_example"No customer filter, because there is nothing to filter by.
The credential decides whose data comes back. There is no customer_id argument anywhere under /v1/me, and sending one is rejected rather than quietly ignored. A resource that exists but belongs to another buyer returns a not-found, so the API will not even confirm that someone else's order id is real.
That is the difference between this and a filtered merchant key. A bug in your front end cannot widen the query, because the query has no width to widen.
- /v1/me/orders
- /v1/me/payments
- /v1/me/refunds
- /v1/me/shipments
- /v1/me/packages
- /v1/me/invoices
- /v1/me/subscriptions
- /v1/me/payment-methods
- /v1/me/addresses
- /v1/me/returns
Plus receipts, invoice PDFs, email changes, and account deletion. Build your own customer account → · Customer sessions →
05The email
Own the mail, or just the links.
Two different asks that most vendors collapse into one. Repointing Flint's links at your pages is a setting. Sending the mail yourself is a build.
curl -X PATCH https://api.withflintpay.com/v1/settings \
-H "Authorization: Bearer $FLINT_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_account": {
"mode": "merchant_hosted",
"merchant_account_url": "https://cedarandstone.com/account",
"route_templates": {
"order": "/orders/{resource_id}",
"subscription": "/subscriptions/{resource_id}",
"return": "/returns/{resource_id}"
}
}
}'Flint keeps sending. Every account link now lands in your app, resolved when the buyer clicks.
curl -X PATCH https://api.withflintpay.com/v1/settings \
-H "Authorization: Bearer $FLINT_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_email_delivery": {
"order_receipts": "merchant_sends",
"fulfillment_updates": "merchant_sends",
"subscription_lifecycle": "flint_sends",
"dunning": "flint_sends",
"returns": "flint_sends",
"invoices": "flint_sends"
}
}'Flint stops sending receipts and delivery updates. It keeps sending the other four.
| Turn this off | Build your send from |
|---|---|
| order_receipts | order.paid |
| fulfillment_updates | order.fulfillment.shipment.updated |
| subscription_lifecycle | subscription.canceled |
| dunning | subscription.payment_failed |
| returns | return.completed |
| invoices | invoice.paid |
Turning a family off stops Flint's email and nothing else. The events behind it keep firing, which is the entire mechanism: you subscribe to what Flint would have written about and write it yourself. Each family maps to more events than deserve a message, so pick the transitions your buyers care about.
Because links resolve at click time rather than at send time, changing where your account lives also fixes the mail you sent last month. Customer email delivery →
FAQ
Questions people actually search for.
Do I have to build a customer account?
No. Every Flint merchant already has one at account.withflintpay.com, and every account link in a receipt, shipping notice, or dunning email points at it. Buyers can track orders, download invoices, manage subscriptions, update a saved card, and start a return there on day one. Branding it, moving it to your domain, and replacing it are three separate decisions you can make later or never.
Can I put the customer account on my own domain?
Yes. Set a custom domain in settings and Flint provisions the certificate and serves the account from account.yourbrand.com. You publish two DNS records that Flint returns to you. The hostname has to be one you have already validated as a payment method domain, which is how Flint knows you control it. Nothing about the account changes except the address bar.
How do I build my own customer account UI?
Authenticate the buyer with your own login, then ask Flint for a customer session scoped to that one buyer. The session secret authorizes 44 endpoints under /v1/me covering orders, delivery, invoices, subscriptions, saved cards, addresses, and returns. There is no customer_id argument anywhere in that namespace, so Flint keeps enforcing ownership on the server and a mistake in your front end cannot show one buyer another buyer's order.
What happens if my custom domain breaks?
Account links fall back to Flint's own domain and keep working. Flint re-checks the hostname on a schedule, and while it is unhealthy every link resolves to the Flint origin instead of a page that will not load. You lose the branded hostname, not the buyer's access to their order.
Can I send the buyer emails myself instead of Flint?
Yes, one family at a time. Receipts, delivery updates, subscription lifecycle, dunning, returns, and invoices each have their own setting. Turning a family off stops Flint's email and nothing else, because the webhook events behind it keep firing. That is what you build your own send from. Flint does not currently support editing its email templates, so branding controls how Flint's email looks and taking a family over gives you what it says.
Can I embed the Flint account in an iframe?
No. The hosted account sends frame-ancestors deny, so it cannot be framed and there is no setting to allow it. To put the account inside your own page, build it against the /v1/me API instead.
Start
The account is already running.
Create a merchant and your buyers have somewhere to go. Everything on this page is a change to something that already works.
