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

# Authentication

> Personal access tokens, OAuth tokens, and the scopes that govern what each may do.

Every API request is authenticated with a Bearer token in the `Authorization` header:

```http theme={"dark"}
GET /api/v1/finance/accounts HTTP/1.1
Host: api.synci.io
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
```

There are two kinds of tokens:

* **Personal access tokens**: for your own scripts and server-to-server calls against your own Synci account. No OAuth flow needed.
* **OAuth access tokens**: for apps that other Synci users authorize. Obtained through the OAuth 2.0 authorization code flow with PKCE. See [Building OAuth apps](/guides/oauth).

Both token types are sent the same way and are subject to the same scope checks.

## Personal access tokens

Create a token in the Synci dashboard under **Developers → Tokens**:

<Steps>
  <Step title="Create the token">
    Click **New token** and give it a descriptive name (for example, "Reporting script").
  </Step>

  <Step title="Restrict it, optionally">
    Restrict the token to specific **scopes** (see the table below) and specific **bank accounts**. A token with no scope restriction has full access to your account.
  </Step>

  <Step title="Copy it immediately">
    For security the token is displayed only once. If you lose it, delete the token and create a new one.
  </Step>
</Steps>

Personal access tokens are valid for **1 year**. You can revoke a token at any time from the same page.

<Note>
  **Migrating a legacy token?** Tokens issued in the older `{id}|{secret}` format keep working for a limited deprecation window but are being retired. Regenerate the token in **Developers → Tokens** and update your integration.
</Note>

## OAuth access tokens

If you are building something other Synci users will connect to, register an OAuth app under **Developers → Apps**. Users approve your app on a consent screen, choose which accounts to share, and your app receives:

* An **access token**, valid for **1 hour**.
* A **refresh token**, valid for **30 days**, which rotates on every use.

The full flow, including PKCE, token exchange, and refresh, is covered in [Building OAuth apps](/guides/oauth).

If your users will never hold a Synci account, a **Managed app** mints tokens for them server-to-server instead, with no consent screen. See [Managed apps](/guides/managed-apps).

## Scopes

Scopes control what a token may do. Personal access tokens can optionally be restricted to a set of scopes; OAuth apps must request them and the user must approve them.

| Scope | Grants |
| - | - |
| `profile:read` | Name, email, and profile details |
| `accounts:read` | View connected financial accounts and balances |
| `accounts:write` | Update, sync, and remove financial accounts, and change their settings |
| `transactions:read` | View transactions |
| `transactions:write` | Create, update, and delete transactions |
| `sensitive:read` | Full account identifiers: IBANs, account and card numbers, and account holder names. Only meaningful together with `accounts:read` or `transactions:read`. |
| `financial-connections:read` | View bank connections and their health |
| `financial-connections:write` | Manage bank connections (reauthorize, disable, remove) |
| `transfer-links:read` | View transfer links and transfer history |
| `transfer-links:write` | Manage transfer links, retry and undo transfers |
| `rules:read` | View rules and rule activity |
| `rules:write` | Manage rules |
| `webhooks:read` | View webhook endpoints |
| `webhooks:write` | Manage webhook endpoints and rotate signing secrets |
| `destinations:read` | View destination connections (YNAB, Lunch Money, Google Sheets) |
| `destinations:write` | Manage destination connections |

<Tip>
  Request the least you need. Users are more likely to approve an app that asks only for what it needs, and app reviews go faster.
</Tip>

### Sensitive identifiers are redacted by default

For third-party apps, sensitive identifiers (IBAN, BBAN, account and card numbers, account holder names) are **always redacted** unless the user granted `sensitive:read`. This is enforced server-side and cannot be switched off by the caller. `sensitive:read` on its own grants nothing; it un-redacts fields on data you can already see through `accounts:read` or `transactions:read`.

### Account selection

Some scopes are account-scoped. When a user authorizes an OAuth app with account-scoped permissions, they pick exactly which accounts the app may access. Personal access tokens can be restricted to specific accounts the same way when you create them.

## How authorization failures look

| Response | Meaning |
| - | - |
| `401 Unauthorized` | Missing, expired, or revoked token. |
| `403 Forbidden` | The token is valid but lacks a scope this endpoint requires. |
| `404 Not Found` | The resource exists but was not granted to this token (for example, an account the user did not select). Synci returns `404` rather than `403` here so tokens cannot probe for the existence of data they were not granted. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.