Skip to content
Coritan Docs

Manage customers

Find, add, edit, credit and close your storefront's customer accounts, sign in as one, and set up their custom fields and OAuth clients.

View as Markdown

Customers are the accounts people hold on your storefront. Most customers register themselves, but you can also create one, correct their details, add credit to their wallet, order a service for them, sign in as them to see your storefront as they do, send them a password reset link, export their data or close their account. Each customer has a page with their services, invoices and credit. The custom fields you store on customers and services, and your OAuth clients, are under Settings, then Customer accounts.

Any member can open the list and a customer's page. What else each task needs:

Task Lowest role Confirm it is you
See a customer's invoices and what they owe Billing No
Raise an invoice for them Billing No
See their credit history Tier 3 support No
Sign in as them with Read-only access Tier 3 support No
Sign in as them with Servers or Full access Admin Yes
Send a password reset link Tier 3 support Yes
Add credit Billing Yes
Create a customer, edit one or order a service for one Admin No
Export a customer's data Admin Yes
Close an account Admin No

When a task asks, the dashboard opens Confirm it is you. Enter your Coritan password and select Confirm. If your account has two-factor sign-in, the dialog asks for the six-digit code from your authenticator instead, or one of your recovery codes. We do not ask again for ten minutes, unless you reload the page.

A customer account belongs to your organization only. It is separate from any Coritan account, even one with the same email.

Note

When Coritan moves your old site's forum to your storefront, an author who has not moved their own account yet is kept as a placeholder with the status unclaimed. A placeholder is not an account. The customer list, its counts, search and your customer limit leave it out, and it cannot sign in. It still opens by its ID, with the note Not an account, but you cannot change its status or email, add credit, invoice it or close it. It becomes that person's account when they move theirs. See Link your old site to your storefront.

  1. In the dashboard, open the organization, then Customers, and choose Customers in the row under it.
  2. Type in Search name, email, company or number to match a name, email, company, public handle or customer number, or choose a status in Any status. Each status in the list shows how many customers hold it for the same search.
  3. Select a column heading to sort the customers on the page by it.
  4. Select a customer to open their page.

The list shows 50 customers to a page, newest first. Each row shows the customer's name and email, their Company, Status, Credit and when they became a customer (Since). The search, the status, the sort and the page stay in the page's address, so a reload or a link you share opens the list as you left it, and All customers on a customer's page takes you back to it. When nothing matches, Reset filters shows every customer again.

The heading shows the customer's name with their status and badges: Email verified or Email unverified, Staff account for an account that belongs to someone on your team, and Social sign-in only for an account with no password. A note under it says when the account cannot sign in: Suspended, Account closed or Banned.

For Billing and above, the line under the name also says what the customer owes, such as Owes €34.80 on 1 invoice, with how much of it is overdue, in red. Select it to open their unpaid and overdue invoices. A customer whose invoices are all settled reads Owes nothing.

Services
Their ten newest services. Select one to open it. With more than ten, the link at the top of the card, such as All 14 services, opens Services filtered to the customer.
Invoices
For Billing and above, their ten newest invoices, each opening on Billing, and a link to the rest when there are more.
Details
Their Email, Name, Company, Phone, Public handle, Country, Currency with where it came from, Credit balance, Last sign-in, and when the account was Created.
Custom fields
Their answers to the custom fields you ask at sign-up or checkout, when they have any.
Credit
For Tier 3 support and above, under the other cards, the balance in their wallet and every entry in and out, newest first and 20 to a page: credit your team added, refunds paid into the wallet and credit spent on invoices, each with the balance after it and a link to the invoice or service it concerns. The link names the invoice by its number, such as Invoice INV-1042, and the service by its hostname when the cards above list them, and reads Open the invoice or Open the service otherwise.

On a phone the cards follow each other in that order, so Details comes before Credit.

The actions are at the top of the page: Edit customer…, Add credit…, and the customer's actions menu with Order service…, New invoice…, Sign in as customer…, Send password reset…, Export data, Open in the staff console and Close account…. New invoice… opens the invoice form on Billing with the customer chosen. Each appears only to the roles that can use it. Once your storefront has a domain, Open in the staff console opens the customer in the staff console in a new tab, with their tickets, notes and history.

  1. On Customers, select New customer….
  2. Enter their Email and a Password of at least 8 characters.
  3. Add a First name, Last name, Company and Phone if you have them.
  4. Leave Preferred currency empty to use the currency of their country, or enter a three-letter code such as EUR.
  5. Select Create customer.

The customer's page opens. The customer can sign in on your storefront straight away, and receives your organization's welcome email. Your webhooks receive customer.created.

  1. Open the customer and select Edit customer….
  2. Change the Email, First name, Last name, Company, Phone, Preferred currency or Status. A new currency applies to the whole account.
  3. Select Save changes.

When you change the email, the customer signs in with the new address from then on, and the old address receives a message about the change. Setting Status to Suspended, Closed or Banned stops the customer's sessions working at once, cancels any open invitations to share a server with them and disconnects their open server consoles. A banned email address cannot sign up again. Closed is refused while the customer has a service that is pending, active or suspended, and the Status field says how many to cancel first. Set Status back to Active to let the customer sign in again. Each change of status is recorded in the audit log, with the status before and after it.

  1. Open the customer and select Add credit….
  2. Enter an Amount above zero, with two decimals at most, in the customer's currency.
  3. Enter a Description if you like. The customer sees it beside the credit in their wallet, and without one it reads Manual credit.
  4. Check the sentence under the fields, which says what the wallet goes from and to, then select the button that names the amount, such as Add €10.00.
  5. Confirm it is you if the dashboard asks.

The dashboard confirms the credit, and the new balance shows under Credit balance and in Credit. The customer can spend it on their next invoice straight away, and an invoice paid from credit is not part of a payout. Each member may add credit 30 times an hour, together with credit added in the staff console.

Order a service for a customer

Section titled Order a service for a customer

Open the customer and choose Order service… in their actions menu, or on their Services card while they have none. The Order a service page opens with the customer chosen, and Cancel brings you back to the customer. Order a service for a customer describes the rest. Only an active customer can be ordered for.

A support session signs one browser tab in to your storefront as the customer, so you can see their account as they do while you help them. It lasts 30 minutes, nobody can renew it, and it opens only on an active account.

  1. Open the customer and choose Sign in as customer… in their actions menu. On Customers, the same item is in the menu at the end of the customer's row.
  2. Under Access, choose how far the session may go:
    • Read-only: see what they see. Coritan refuses every change.
    • Servers: also change their servers and snapshots. Their account and billing stay read-only.
    • Full access: make any change they could, except change their profile, password, email, two-factor, sign-in methods or sessions, or close their account.
  3. Enter a Reason. Full access needs one of at least 5 characters, and for the others it is optional. It goes on the record with the session.
  4. Select Open session. For Servers and Full access, confirm it is you if the dashboard asks.

The dialog says Session opened with the time the session ends, and a new tab opens on your storefront, signed in as the customer. If your browser blocked the tab, select Open the session again, which works until the session ends. Select Done to close the dialog.

The tab opens on your custom domain. With no custom domain, it opens on the Storefront address in your store's settings. It lands on /auth/callback there, so that page must take the session: the storefronts Coritan serves and the Next.js starter do, and a storefront you build follows Receive a support session. On each of them, a banner at the top of the tab names the customer's account and has End session.

Each member may open 20 support sessions an hour, together with those opened from the staff console. The audit log records each session you open, with its access and reason, and every change a Servers or Full access session makes, against you.

Coritan does not email the customer. Where your storefront shows the customer their session list, it lists the support session with your address. The session ends when its 30 minutes run out, when you select End session in the tab's banner, or when the customer signs out their other sessions. You can also end it from the staff console (Help a customer sign in).

  1. Open the customer and choose Send password reset… in their actions menu.
  2. Select Send reset link.
  3. Confirm it is you if the dashboard asks.

The customer receives your storefront's password reset email, with a link to choose a new password. The link works for 2 hours, and a forgot-password request from the customer does not cancel it. Their password and their sessions stay as they are until they use it. If the email did not go out, the dashboard says so: check Email sending under Settings, then try again. Only an active account can be sent a link, and each member may send 20 an hour.

  1. Open the customer and choose Export data in their actions menu.
  2. Confirm it is you if the dashboard asks.

Your browser downloads everything held about the customer as one JSON file, for a privacy request. It includes your team's notes and the internal notes on their tickets, so review it before you send it. It holds the account's attribution record and the record of each order. Passwords, session tokens, two-factor secrets, payment tokens and the files on their servers are not in it. Each export is recorded in the audit log, and each member may export 12 times an hour, together with exports from the staff console.

  1. Open the customer and choose Close account… in their actions menu.
  2. Type the customer's email to confirm, then select Close account.

Warning

The customer is signed out everywhere and can no longer sign in, and invitations waiting for them to share another customer's server are cancelled. Their invoices stay.

An account with a service that is pending, active or suspended cannot be closed: closing it would leave the services running with nobody to bill. Cancel those services first, then close the account. An unpaid invoice does not stop a close.

The dashboard confirms it and says how many storefront sessions ended, such as Alex Martin's account closed, and 2 storefront sessions ended. The account stays on record with the status closed, and its page says Account closed. Closing is recorded in the audit log. To reopen it, select Edit customer… and set Status back to Active; the customer then signs in again. Closing here keeps the customer's details. To close an account for good and anonymise it, use the staff console.

Custom fields hold extra facts about a customer or a service, such as a VAT number. Every member can see them under Settings, then Customer accounts. Adding and deleting them takes the owner or admin role.

  1. In the organization, open Settings, then Customer accounts, and in Custom fields select New field….
  2. Enter a Label, such as VAT number, and a Key, such as vat_number. The key starts with a letter, uses lowercase letters, digits and underscores, and cannot be changed later.
  3. Choose a Type: Text, Number, Choice from a list with its Options one per line, Yes or no, Date or JSON.
  4. Choose whether it Applies to a Customer, a Service or a Product.
  5. Add a Default value, and tick Required if customers must fill it in when they sign up or order.
  6. Select Add field.

Each key can be used once for each kind of record, so a second customer field with the key vat_number is refused under Key; a service field can still use it. When you or your storefront send custom field values for a customer, the API refuses a key that is not defined (Unknown custom field 'vat') and a missing required one (Required custom field 'vat_number' is missing).

To delete a field, select the delete button on its row, type its key, then select Delete field. The answers customers already gave stay on their accounts, and their page still shows them, under the key instead of the label. A field you add again with the same key shows them under its label. Adding and deleting fields, like creating and deleting OAuth clients, is recorded in the audit log.

The OAuth clients card, under Settings, then Customer accounts, is for owners and admins. It registers an application with its Name, Redirect URIs (full http or https addresses, one per line), Allowed scopes and Grant types, both comma-separated. Select New client…, fill them in and select Create client. The client secret is shown once, so copy it before you close the dialog.

To delete a client, select the delete button on its row, type its name, then select Delete client. Its client ID stops working at once, and you cannot undo it.

Note

Coritan stores the client and its secret, but it does not run an OAuth sign-in flow for them yet, so an application cannot use a client to sign a customer in.

Email already registered in this organization
Another customer of your organization has that email. Search for them instead.
Customer limit reached (100/100)
Your organization holds as many customers as Coritan allows it. Close accounts you no longer need, or ask support to raise the limit.
Currency GBP is not enabled
Coritan does not take payment in that currency. Leave the currency empty or choose another.
Amount must be positive
Enter an amount above zero.
Two-factor sign-in is on for this account, so enter a code from your authenticator.
Confirm it is you now asks for the code your authenticator app shows, or one of your recovery codes. Enter it and select Confirm.
The reset email to … did not go out.
Your storefront could not send the email. Check Email sending under Settings, then send the link again.
Too many requests for this action. Try again later.
You added credit, sent reset links or exported data more often than the hourly limit allows. Wait, then try again.
Sign in as customer… is missing
The customer is not active, or your role is below Tier 3 support. Reactivate the account with Edit customer…, or ask a member with a higher role.
Servers and Full access cannot be chosen
The dialog says Servers and Full access need an owner or admin. Ask an owner or admin to open the session.
The dialog says No storefront to open it on
Your organization has neither a custom domain nor a storefront address, so the session has nowhere to open, and Coritan does not open one. Set a custom domain, or a Storefront address in your store's settings, then sign in as the customer again.
The new tab does not open your storefront
A session opens on your custom domain whenever one is saved, verified or not. Until Coritan serves your storefront there, the domain's card under Settings, Storefront says Not pointed at your storefront, and Set your custom domain says what to do.
This customer is suspended and cannot be impersonated.
A support session opens only on an active account, and the message names the account's status. Reactivate it with Edit customer… first, or read the account from its page.
Say why you need full access, in at least 5 characters. It goes on the record.
Full access needs a Reason of at least 5 characters.
You can open 20 support sessions an hour. Try again later.
Each member may try 20 times an hour, from the dashboard and the staff console together. Every try counts, including one Coritan refused. Opening a Servers or Full access session counts twice when the dashboard first has to ask you to confirm it is you. Wait, then try again.
There is already a customer field named vat_number. Choose another name.
Your organization already has a field with that key on the same kind of record. Choose another key, or use the field you have.
409 A placeholder for a moved forum author cannot ...
The customer is a placeholder for the author of forum threads moved from your old site. It becomes an account when its owner moves theirs; until then nobody can change it.
Cancel your 2 active services first. Closing now would leave them running with nobody to bill.
The customer still has services that are pending, active or suspended. Cancel them from the customer's Services card or from Services, then close the account.

List customers, newest first. q searches, status_filter takes active, suspended, closed or banned, and limit (1–200, default 50) and offset page the list. Add with_total=true for {items, total, limit, offset, counts}, where counts gives the number of customers in each status for the same search. The list, total and counts leave out unclaimed placeholders.

Shell
curl "https://api.coritan.com/api/v1/orgs/acme/customers?q=alex&with_total=true" \
  -H "Authorization: Bearer $CORITAN_TOKEN"

Create a customer with email and password (at least 8 characters), and optionally first_name, last_name, company, phone, currency and custom_fields:

Shell
curl -X POST https://api.coritan.com/api/v1/orgs/acme/customers \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "alex@example.com", "password": "a-long-passphrase", "first_name": "Alex", "currency": "EUR"}'

Read one with GET /customers/{customer_id}, and change it with PATCH on the same path and any of the fields above plus status, which takes the same four words and answers 422 for any other. DELETE /customers/{customer_id} closes the account, ends its storefront sessions and answers how many:

JSON
{"message": "Customer deactivated", "status": "closed", "sessions_ended": 2}

It is recorded in the audit log as customer.closed, and a PATCH with "status": "active" reopens the account. A PATCH that changes status is recorded as customer.status_changed, with {"status": {"from": "active", "to": "suspended"}} and, for any status but active, sessions_ended. While the customer has a service that is pending, active or suspended, DELETE and a PATCH to closed answer 409 {"detail": {"code": "active_services", "message": "Cancel your 2 active services first. Closing now would leave them running with nobody to bill."}} and change nothing. For a placeholder, a status, a new email, credit and DELETE answer 409.

Adding credit, sending a reset link, exporting data and opening a servers or full support session answer 403 with reauth_required until you have confirmed it is you in the last 10 minutes. Send your password, or a code when two-factor sign-in is on, to POST /step-up, then send the token it answers as the X-Org-Step-Up header. A staff console session confirms with its own step-up instead (Confirm it is you).

Add credit with the amount and the description as query parameters. The answer is the new balance:

Shell
curl -X POST "https://api.coritan.com/api/v1/orgs/acme/customers/812/credit/add?amount=10.00&description=Goodwill" \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "X-Org-Step-Up: $STEP_UP_TOKEN"
JSON
{"credit_balance": 25.0}

The rest of a customer's page uses the staff routes, which a member's access token reaches too:

  • GET /staff/customers/{customer_id}/credit-ledger answers the wallet's balance and currency, and its entries newest first, each with amount, balance_after, description, kind, invoice_id and org_service_id. limit (1–200, default 50) and offset page them.
  • POST /staff/customers/{customer_id}/reset-password with no body emails the storefront's reset link, which works for 2 hours, and answers link_sent. With a password in the body it sets that password instead and ends every session the customer has.
  • GET /staff/customers/{customer_id}/data-export answers the JSON file for a privacy request.

Sign in as a customer with POST /staff/customers/{customer_id}/impersonate. mode is read_only (the default), servers or full. reason takes up to 300 characters, and full needs at least 5. next is a path on your storefront to open once the customer is signed in. Send "origin": "dashboard", as the dashboard does: when such a session ends, the storefronts Coritan serves keep the tab on the storefront. With the default, staff, they send it back to the customer's page in the staff console.

Shell
curl -X POST https://api.coritan.com/api/v1/orgs/acme/staff/customers/812/impersonate \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "X-Org-Step-Up: $STEP_UP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode": "full", "reason": "Their server will not start after an update", "origin": "dashboard"}'
JSON
{
  "access_token": "...",
  "expires_in": 1800,
  "expires_at": "2026-09-26T10:00:00+00:00",
  "mode": "full",
  "read_only": false,
  "elevated": true,
  "org_slug": "acme",
  "customer_email": "alex@example.com",
  "portal_url": "https://example.com/auth/callback#access_token=...&impersonated=1&elevated=1&mode=full&from=dashboard"
}

access_token is the customer's, for 1800 seconds, and elevated is true for servers and full. Open portal_url in a new tab with noopener, and share it with nobody: whoever opens it is signed in as the customer until the session ends. Open a support session lists what the address carries. The audit log records the session as customer.impersonated, with its mode, reason and origin, and each change a servers or full session makes as portal.elevated_write or portal.full_access_write. Coritan checks the request in this order:

  • 403 with Support access required below Tier 3 support.
  • 429 with rate_limited after 20 tries in an hour, counting those refused below.
  • 403 with Only an org admin can open a session that changes a customer's servers. or Only an org admin can open a full-access session as a customer. below admin.
  • 403 with reauth_required for servers or full, until you confirm it is you.
  • 400 with Say why a full-access session is needed (at least a few words); it goes on the record. for full with a shorter reason.
  • 404 with Customer not found.
  • 409 with This customer is suspended and cannot be impersonated., naming the status, for an account that is not active.
  • 409 with no_storefront when your organization has neither a custom domain nor a storefront address. Coritan opens no session.

Custom fields are GET /custom-fields (filter with applies_to), POST /custom-fields with field_name, label, field_type (string, number, boolean, date, json or enum), applies_to (customer, service or product), options, default_value and required, which answers 409 when the organization already has a field with that field_name and applies_to, and DELETE /custom-fields/{field_id}, which leaves stored values as they are. OAuth clients are GET /oauth-clients, POST /oauth-clients with name, redirect_uris, allowed_scopes and grant_types, whose answer carries client_secret once, and DELETE /oauth-clients/{client_id}, which takes the client's id or its client_id and answers 204.

API operations on this page

MethodPathWhat it does
GET/api/v1/orgs/{org_slug}/customersThe org's customers, newest first
POST/api/v1/orgs/{org_slug}/customersCreate customer
GET/api/v1/orgs/{org_slug}/customers/{customer_id}One customer account
PATCH/api/v1/orgs/{org_slug}/customers/{customer_id}Change a customer's details or standing
DELETE/api/v1/orgs/{org_slug}/customers/{customer_id}Close a customer's account and end its sessions; it can be reopened
POST/api/v1/orgs/{org_slug}/customers/{customer_id}/credit/addAdd amount to a customer's wallet
GET/api/v1/orgs/{org_slug}/staff/customers/{customer_id}/credit-ledgerThe customer's wallet, newest entry first
POST/api/v1/orgs/{org_slug}/staff/customers/{customer_id}/reset-passwordStaff reset customer password
GET/api/v1/orgs/{org_slug}/staff/customers/{customer_id}/data-exportEverything held about the customer, as one JSON file, for a privacy request
POST/api/v1/orgs/{org_slug}/staff/customers/{customer_id}/impersonateStaff impersonate customer
GET/api/v1/orgs/{org_slug}/custom-fieldsList custom fields
POST/api/v1/orgs/{org_slug}/custom-fieldsA field the brand keeps on its customers, services or products
DELETE/api/v1/orgs/{org_slug}/custom-fields/{field_id}Delete a custom field
GET/api/v1/orgs/{org_slug}/oauth-clientsList OAuth clients
POST/api/v1/orgs/{org_slug}/oauth-clientsAn OAuth client that signs the brand's customers in elsewhere
DELETE/api/v1/orgs/{org_slug}/oauth-clients/{client_id}Delete OAuth client