> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowmaticai.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Flowmatic Authentication: JWT Tokens and Refresh Guide

> Register, verify your email, and obtain JWT tokens to authenticate every Flowmatic API request via the Authorization: Bearer header.

Every Flowmatic API request — except the registration, verification, and login endpoints themselves — requires a valid JSON Web Token (JWT) passed in the `Authorization` header. This guide covers the complete authentication lifecycle: creating your account, verifying your email, obtaining tokens, using them in requests, and refreshing them before they expire. Follow these steps once to bootstrap your integration, then automate token refresh so your application never has to ask users to log in again.

<Warning>
  Never hard-code your `accessToken` or `refreshToken` in source code, client-side JavaScript, or public repositories. Store tokens in environment variables, a secrets manager, or a secure server-side session store. Treat them with the same care as passwords.
</Warning>

***

## Step 1 — Register an Account

Send a `POST` request to `/api/auth/register` to create a new Flowmatic account. On success, Flowmatic sends an OTP (one-time passcode) to the email address you provide. You will need this OTP to verify your email in the next step.

<ParamField body="email" type="string" required>
  The email address for your new account. Must be a valid, deliverable address — this is where OTPs and workflow notifications are sent.
</ParamField>

<ParamField body="password" type="string" required>
  Your chosen password. Minimum 8 characters. Flowmatic stores your password securely and never exposes it after account creation.
</ParamField>

<ParamField body="fullName" type="string" required>
  Your full name. Displayed in the dashboard and included in account-level emails.
</ParamField>

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl -X POST https://api.flowmatic.io/api/auth/register \
      -H "Content-Type: application/json" \
      -d '{
        "email": "you@example.com",
        "password": "supersecret123",
        "fullName": "Jane Smith"
      }'
    ```
  </Tab>

  <Tab title="Response (201 Created)">
    ```json theme={null}
    {
      "message": "Registration successful. Please check your email for a verification code."
    }
    ```
  </Tab>

  <Tab title="Error (409 Conflict)">
    ```json theme={null}
    {
      "error": "EMAIL_ALREADY_REGISTERED",
      "message": "An account with this email address already exists."
    }
    ```
  </Tab>
</Tabs>

<Note>
  If you already have an account and just need a new OTP, skip to [Resend OTP](#resend-otp) below. Do not register again — duplicate registration attempts return a `409` error.
</Note>

***

## Step 2 — Verify Your Email Address

After registration, Flowmatic locks the account until the email address is confirmed. Submit the OTP from your inbox to unlock it. On success, Flowmatic immediately returns an `accessToken` and a `refreshToken` — you can start making authenticated requests without a separate login call. OTPs are single-use and expire after 10 minutes.

<ParamField body="email" type="string" required>
  The email address you registered with.
</ParamField>

<ParamField body="otp" type="string" required>
  The six-digit code delivered to your inbox after registration (or after a resend request).
</ParamField>

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl -X POST https://api.flowmatic.io/api/auth/verify-email \
      -H "Content-Type: application/json" \
      -d '{
        "email": "you@example.com",
        "otp": "847291"
      }'
    ```
  </Tab>

  <Tab title="Response (200 OK)">
    ```json theme={null}
    {
      "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfMDFoeC4uLiIsImV4cCI6MTcxNTM0NTYwMH0.abc123",
      "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4gZXhhbXBsZQ=="
    }
    ```
  </Tab>

  <Tab title="Error (400 Bad Request)">
    ```json theme={null}
    {
      "error": "INVALID_OR_EXPIRED_OTP",
      "message": "The verification code is invalid or has expired. Please request a new one."
    }
    ```
  </Tab>
</Tabs>

<ResponseField name="accessToken" type="string">
  A signed JWT used to authenticate API requests. Include it in the `Authorization: Bearer` header. Use `POST /api/auth/login` to check the `expiresIn` value, or refresh proactively before it expires.
</ResponseField>

<ResponseField name="refreshToken" type="string">
  A long-lived token used to request new access tokens via `POST /api/auth/refresh-token` without re-entering credentials.
</ResponseField>

### Resend OTP

If your OTP expired or never arrived, request a fresh one. Flowmatic invalidates any previously issued OTP before sending the new one, so only the latest code is valid.

<ParamField body="email" type="string" required>
  The email address associated with the unverified account.
</ParamField>

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl -X POST https://api.flowmatic.io/api/auth/resend-otp \
      -H "Content-Type: application/json" \
      -d '{
        "email": "you@example.com"
      }'
    ```
  </Tab>

  <Tab title="Response (200 OK)">
    ```json theme={null}
    {
      "message": "A new verification code has been sent to your email address."
    }
    ```
  </Tab>
</Tabs>

<Note>
  Resend requests are rate-limited. If you trigger this endpoint too frequently, you will receive a `429 Too Many Requests` response. Wait at least 60 seconds between resend attempts.
</Note>

***

## Step 3 — Log In

For any session after your initial verification, use `POST /api/auth/login` to exchange your credentials for a fresh JWT `accessToken` and a `refreshToken`. Both are required for a complete integration — the `accessToken` authenticates your API calls, and the `refreshToken` lets you obtain a new `accessToken` without asking the user to re-enter their password.

<ParamField body="email" type="string" required>
  Your verified email address.
</ParamField>

<ParamField body="password" type="string" required>
  Your account password.
</ParamField>

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl -X POST https://api.flowmatic.io/api/auth/login \
      -H "Content-Type: application/json" \
      -d '{
        "email": "you@example.com",
        "password": "supersecret123"
      }'
    ```
  </Tab>

  <Tab title="Response (200 OK)">
    ```json theme={null}
    {
      "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfMDFoeC4uLiIsImV4cCI6MTcxNTM0NTYwMH0.abc123",
      "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4gZXhhbXBsZQ==",
      "expiresIn": 3600,
      "tokenType": "Bearer"
    }
    ```
  </Tab>

  <Tab title="Error (401 Unauthorized)">
    ```json theme={null}
    {
      "error": "INVALID_CREDENTIALS",
      "message": "The email or password you entered is incorrect."
    }
    ```
  </Tab>
</Tabs>

<ResponseField name="accessToken" type="string">
  A signed JWT used to authenticate API requests. Include it in the `Authorization: Bearer` header. Expires after `expiresIn` seconds.
</ResponseField>

<ResponseField name="refreshToken" type="string">
  A long-lived token used to request new access tokens. Does not expire on a fixed schedule but is invalidated when you call the logout endpoint or refresh it (single-use).
</ResponseField>

<ResponseField name="expiresIn" type="integer">
  The number of seconds until the `accessToken` expires. Typically `3600` (one hour).
</ResponseField>

<ResponseField name="tokenType" type="string">
  Always `"Bearer"`. This is the authentication scheme you must use in the `Authorization` header.
</ResponseField>

<Warning>
  The `refreshToken` is single-use. Once you exchange it for a new `accessToken`, the old `refreshToken` is invalidated and a fresh one is issued. Always persist the latest `refreshToken` returned by `/api/auth/refresh-token`.
</Warning>

***

## Step 4 — Authenticate Requests

With your `accessToken` in hand, add it to every API request using the standard HTTP `Authorization` header:

```
Authorization: Bearer <accessToken>
```

Here is an example of an authenticated request to list your workflows:

```bash theme={null}
curl -X GET https://api.flowmatic.io/api/workflows \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

If you omit the header or supply an expired token, Flowmatic returns `401 Unauthorized`:

```json theme={null}
{
  "error": "UNAUTHORIZED",
  "message": "Missing or invalid Authorization header. Please provide a valid Bearer token."
}
```

<Info>
  The `Authorization` header is **case-insensitive** for the header name but the scheme must be exactly `Bearer` (capital B). Most HTTP clients handle this automatically.
</Info>

***

## Step 5 — Refresh Your Access Token

Access tokens expire after `expiresIn` seconds (typically one hour). Rather than asking users to log in again, exchange your `refreshToken` for a new pair of tokens using `POST /api/auth/refresh-token`.

<ParamField body="refreshToken" type="string" required>
  The `refreshToken` received from your most recent login or token-refresh call. This token is invalidated once used.
</ParamField>

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl -X POST https://api.flowmatic.io/api/auth/refresh-token \
      -H "Content-Type: application/json" \
      -d '{
        "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4gZXhhbXBsZQ=="
      }'
    ```
  </Tab>

  <Tab title="Response (200 OK)">
    ```json theme={null}
    {
      "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfMDFoeC4uLiIsImV4cCI6MTcxNTM0OTIwMH0.xyz789",
      "refreshToken": "bmV3IHJlZnJlc2ggdG9rZW4gZ2VuZXJhdGVk",
      "expiresIn": 3600,
      "tokenType": "Bearer"
    }
    ```
  </Tab>

  <Tab title="Error (401 Unauthorized)">
    ```json theme={null}
    {
      "error": "INVALID_REFRESH_TOKEN",
      "message": "The refresh token is invalid, expired, or has already been used."
    }
    ```
  </Tab>
</Tabs>

<ResponseField name="accessToken" type="string">
  Your new access token. Replace the previous value in your token store immediately.
</ResponseField>

<ResponseField name="refreshToken" type="string">
  A new refresh token. Persist this and discard the old one — the old token is now invalid.
</ResponseField>

***

## Token Expiry and Refresh Strategy

Understanding when and how to refresh keeps your integration running smoothly without unnecessary re-authentication prompts.

| Token          | Typical Lifetime             | When to Refresh                                            |
| -------------- | ---------------------------- | ---------------------------------------------------------- |
| `accessToken`  | 1 hour (`expiresIn` seconds) | When a request returns `401`, or proactively before expiry |
| `refreshToken` | Long-lived (days to weeks)   | After each use — a new one is always issued on refresh     |

**Recommended approach for server-side integrations:**

1. After login, store `accessToken`, `refreshToken`, and a calculated `expiresAt` timestamp (`Date.now() + expiresIn * 1000`).
2. Before every API request, check if `expiresAt` is within 60 seconds of the current time.
3. If so, call `POST /api/auth/refresh-token` first, update both stored tokens and `expiresAt`, then proceed with the original request.
4. If a request still returns `401` after a refresh (rare, but possible if the refresh token was also invalidated), fall back to prompting for credentials.

```bash theme={null}
# Example: check current token validity, then refresh if needed
# (pseudo-bash for illustration)

EXPIRES_AT=1715345600   # stored from login
NOW=$(date +%s)

if [ $((EXPIRES_AT - NOW)) -lt 60 ]; then
  echo "Token expiring soon — refreshing..."
  curl -X POST https://api.flowmatic.io/api/auth/refresh-token \
    -H "Content-Type: application/json" \
    -d '{ "refreshToken": "'$REFRESH_TOKEN'" }'
fi
```

<Warning>
  If your `refreshToken` is compromised, an attacker can silently obtain new `accessToken`s indefinitely. Immediately log out all sessions from the Flowmatic dashboard under **Account → Security → Revoke All Sessions** to invalidate all outstanding refresh tokens.
</Warning>

***

## Authentication Endpoint Summary

| Method | Endpoint                  | Auth Required | Purpose                               |
| ------ | ------------------------- | ------------- | ------------------------------------- |
| `POST` | `/api/auth/register`      | No            | Create a new account                  |
| `POST` | `/api/auth/verify-email`  | No            | Confirm email with OTP                |
| `POST` | `/api/auth/resend-otp`    | No            | Re-send a verification OTP            |
| `POST` | `/api/auth/login`         | No            | Obtain access + refresh tokens        |
| `POST` | `/api/auth/refresh-token` | No            | Exchange refresh token for new tokens |

All other Flowmatic endpoints require `Authorization: Bearer <accessToken>`.

<Note>
  Looking for a complete walkthrough that ties authentication into a real workflow? See the [Quickstart guide](/quickstart) — it covers every step from registration through to monitoring a live run.
</Note>
