# Authentication

Sign in with your login's email and password to get a token, then send the token as a bearer token on every other call. A few calls need no token: [Sign in](/reference/sign-in), [List countries](/reference/list-countries) and [List currencies](/reference/list-currencies).

## Sign in

`POST /client_api/v2/auth/sign_in`

```bash
curl -X POST "https://sandbox-api.vatit-stream.com/client_api/v2/auth/sign_in" \
  -H "Content-Type: application/json" \
  -d '{
    "api_user": {
      "email": "integrations@globaltradecorp.example",
      "password": "your-password"
    }
  }'
```

The answer holds the token:

```json
{
  "token": "eyJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImludGVncmF0aW9ucy4uLiJ9.tQ3m0Yk9v1S7bT2n5Zq8Lw4HcXr6JdPaUeVgNiOfMhA"
}
```

A wrong email or password answers `401`:

```json
{
  "success": false,
  "error": "Invalid email or password",
  "errors": []
}
```

## Using the token

Send it in the `Authorization` header of every other call:

```bash
curl "https://sandbox-api.vatit-stream.com/client_api/v2/orders" \
  -H "Authorization: Bearer $API_TOKEN"
```

A token lasts **one week**. Sign in again before then, or when a call answers `401`.

## When a call answers 401

A `401` always means: sign in again. Its `error` says why:

| `error` | Why |
|---|---|
| `You need to sign in or sign up before continuing.` | The call sent no token. |
| `Signature has expired` | The token is more than a week old. |
| `revoked token` | The token was signed out. |
| `Signature verification failed` | The token was changed, or comes from the other environment. |
| `Invalid base64 encoding` | The header doesn't hold a whole token. |

A `403` is different: your token is fine, but your login isn't allowed to do this, for example creating companies without the reseller permission. Signing in again won't help.

## Keeping it safe

- Call the API from your server, never from a browser or a mobile app, so the token and your password stay out of your users' hands.
- Keep the password and the token out of source control. Read them from your environment or a secrets store.
- Sandbox and production have separate logins. A sandbox token doesn't work on production.
