Skip to content

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 seesWhereWhat it costs you
Flint's account, Flint's brandaccount.withflintpay.comNothing. It is already on.
Your colors, your name, no Flint markaccount.withflintpay.comOne settings call.
The same account, your addressaccount.yourbrand.comOne settings call and two DNS records.
Your account, your codeyourbrand.com/accountYou 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.

one call
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.

What the settings above are styling: order history, subscriptions, saved cards, and profile, in one place a buyer already has.
  • 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.

set the hostname
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.

then read back the records
{
  "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.

after your own login
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.

a buyer-scoped credential
{
  "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.

the buyer's orders
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.

just the links
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.

or the whole family
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 offBuild your send from
order_receiptsorder.paid
fulfillment_updatesorder.fulfillment.shipment.updated
subscription_lifecyclesubscription.canceled
dunningsubscription.payment_failed
returnsreturn.completed
invoicesinvoice.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.