Authentication
Every request needs exactly one of three credentials, sent as a standard bearer header:
Authorization: Bearer <token>
| Credential | Looks like | Use for |
|---|---|---|
| Account token | a JWT | Managing your account — instances, API keys, billing |
| Personal access token | pat_... | Same as above, for scripts/automation (no expiry) |
| Instance API key | sk_... | Sending messages, webhook config, for one instance |
Wherever AccountToken is accepted, a personal access token works identically — they're fully
interchangeable. Where a route accepts both an account token and an instance API key, send
whichever you have. The one exception: /instances/:id/messages/* always requires the
instance's own API key, since that's your server's own outbound integration, not a dashboard
session.
Account token — magic link
There's no password to set. Request a login link by email:
curl -X POST https://app.tarceel.com/auth/request-link \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "name": "Jane Doe", "phone": "+15551234567"}'
Always returns 202 — check your email, click the link, and it lands you on
GET /auth/verify?token=..., which returns:
{ "token": "<jwt>" }
That JWT is your account token — valid for 30 days. name/phone are only required (and
only used) on first signup; a returning login ignores them.
You can also sign in with Google (GET /auth/google) — it converges on the same account for the
same email, so a customer who signs up with email and later clicks "Sign in with Google" lands in
the same account, not a second one.
Once set up (Settings → Security in the dashboard), you can log in with a 6-digit code from an authenticator app instead of waiting on an email every time. This is an alternative login method, not additive two-factor — email stays available as a fallback at all times.
Personal access tokens — for scripts
A magic link assumes a human with an inbox. For a script, CI pipeline, or automation tool that needs to create instances or manage billing with nobody around to click a link, create a personal access token instead — it never expires until you revoke it.
Dashboard → API Tokens → + Create token, or:
curl -X POST https://app.tarceel.com/account/tokens \
-H "Authorization: Bearer <account token or existing pat_...>" \
-H "Content-Type: application/json" \
-d '{"name": "CI pipeline"}'
The raw pat_... value is shown exactly once, at creation — store it immediately. Revoke it any
time with DELETE /account/tokens/:id.
A personal access token does not cover message sending — that's always the instance's own API key, below.
Instance API key — for sending messages
Every instance has its own sk_... key, shown exactly once: right after
POST /instances succeeds, or after rotating it.
curl -X POST https://app.tarceel.com/instances \
-H "Authorization: Bearer <account token>" \
-H "Content-Type: application/json" \
-d '{"billingMode": "prepaid", "name": "Support line"}'
{ "instanceId": "clx1234...", "apiKey": "sk_..." }
Lost it? Open the instance in the dashboard → Overview → Credentials (has a Copy button),
or rotate a fresh one with POST /instances/:id/api-key/rotate — this invalidates the old key
immediately, so update anything still using it.
If you're building a third-party integration (a CRM, an automation tool) rather than calling the
API from your own backend directly, see Connect — it gets an instanceId/apiKey
pair into your software with one click from your user, no copy-pasting required.
What needs which credential
| You want to... | Credential |
|---|---|
| Create/list/pause/delete an instance | Account token (or PAT) |
| Rotate or revoke an instance's API key | Account token (or PAT) — or the instance's own key |
| View/manage billing, checkout | Account token (or PAT) |
| Configure a webhook, view delivery history | Account token (or PAT) — or the instance's own key |
| Send a message, check message status | Instance API key only |
A token from one account can never manage another account's instance, even just to rotate its
key — every account-scoped route verifies ownership of the instanceId in the URL.