Quick start
This page assumes you already have a running FlowDesk installation. If you have not set one up yet, start with Installation → Requirements.
The examples below use https://api.example.com as the API address; replace it with your own
installation’s. You get that address and your first user credentials from your FlowDesk
administrator (the team that ran the installation).
Opening a request needs an API token; the JWT you get by signing in to the dashboard is not valid for it. Because the token is created from the dashboard, sign in there first. The Authentication page explains why these two credentials are separate.
1. Sign in to the dashboard
Section titled “1. Sign in to the dashboard”This step depends on your installation’s authentication provider; find out which one is enabled from Configuration → Authentication or from the team that ran the installation.
If EmailPassword is enabled (it works as below): on a fresh installation the API creates
the admin@shft.co user automatically on first boot, with a seeded password. That password is
not published here; get it from the team that ran your installation. Change it immediately
after the first sign-in.
curl -s -X POST https://api.example.com/v1/dashboard/auth/login \ -H "Content-Type: application/json" \ -d '{ "email": "admin@shft.co", "password": "<the-seeded-password-from-your-install-team>" }'If only Keycloak is enabled the endpoint above does not work: before a password-based
sign-in the API checks that the EmailPassword provider is enabled, and rejects the request when
it is not. Sign in from the dashboard instead, with a Keycloak realm user whose e-mail matches a
FlowDesk user exactly; for details see
Configuration → Authentication.
Expected response (200):
{ "success": true, "data": { "accessToken": "eyJhbGciOiJSUzI1NiIs...", "accessTokenExpiresAt": "2026-08-13T10:15:00Z", "refreshToken": "8f2c1a...", "refreshTokenExpiresAt": "2026-08-20T10:00:00Z" }, "error": null}You will use accessToken in the next step: for dashboard endpoints only, not for integration
endpoints.
2. Create an API token
Section titled “2. Create an API token”This step is done in the dashboard by an administrator (it needs the
api-tokens:api-token-create:save permission). A token is bound to one or more pools, or to all
of them (allPools: true): that scope decides which pools requests can be opened in with the
token. Check your own installation’s pool ids in the dashboard (the Pools page); the 1 below is
only an example.
curl -s -X POST https://api.example.com/v1/dashboard/api-tokens \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \ -H "Content-Type: application/json" \ -d '{ "name": "First integration", "scopes": ["tickets:read", "tickets:write"], "poolIds": [1], "allPools": false }'Expected response (201):
{ "success": true, "data": { "id": 1, "token": "fd_ab12cd34ef...9f", "tokenPrefix": "fd_ab12c" }, "error": null}The token field appears in this response only. From then on the server stores only its
hash; if you lose it, the only thing you can do is create a new token. Save the value to a secret
manager now.
3. Open your first request
Section titled “3. Open your first request”You can now call v1/integration/tickets with the API token:
curl -s -X POST https://api.example.com/v1/integration/tickets \ -H "Authorization: Bearer fd_ab12cd34ef...9f" \ -H "Content-Type: application/json" \ -d '{ "subject": "Test request", "description": "The first request opened from the quick start guide.", "priority": "High", "requesterFullName": "Alex Morgan", "requesterEmailAddress": "alex@example.com" }'The example above uses High for priority. For every value this field accepts and its
validation rules, see Creating requests.
Expected response (202 Accepted):
{ "success": true, "data": { "trackingKey": "TI1LL2-s20EICNKMwYbzr_jzpr_kzZN5bRjz8gdGYS8yZUsm6w6EScY9FKSjTxJV", "status": "queued" }, "error": null}trackingKey is not a human-readable format: it is a 64-character, URL-safe random string (it
carries no FD-… style prefix and no predictable pattern). You cannot construct or guess one;
use only the value the server returns.
This endpoint returns 202 immediately; pool assignment and the welcome e-mail run outside
your request, in the background. The example above did not send a poolId, because the token you
created in step 2 is bound to a single pool: in that case that one pool is assumed automatically.
For the full pool-selection rules see the “Pool selection” section on
Creating requests.
Send an Idempotency-Key header so you can safely retry after something like a network timeout:
the same key with the same body does not open a second request, and returns the original response
again.
4. Confirm the request really was created
Section titled “4. Confirm the request really was created”Receiving a trackingKey does not mean the request was created: it means it was queued. Ask
the endpoint below after a short delay (for example a 1s, 2s, 4s backoff):
curl -s https://api.example.com/v1/integration/tickets/by-tracking-key/TI1LL2-s20EICNKMwYbzr_jzpr_kzZN5bRjz8gdGYS8yZUsm6w6EScY9FKSjTxJV \ -H "Authorization: Bearer fd_ab12cd34ef...9f"If the request has not been created yet this endpoint returns 404: that is not an error, it is
the expected first state. Once the request exists, the same endpoint returns 200 with the
request’s full body.
What’s next
Section titled “What’s next”- The full reference for every integration endpoint (listing, filtering, rate limits, error codes): API Reference
- Opening requests automatically from incoming e-mail: E-mail settings
- Setting up your own installation from scratch: Installation