# Authentication (/developers/authentication)

Every v1 request carries your application's app id and app secret in one HTTP Basic header. There
are no other credentials: no bearer tokens and no publishable key.

## The header [#the-header]

```text
Authorization: Basic base64(app_id:app_secret)
```

| Credential | Prefix          | Where it lives                                                        |
| ---------- | --------------- | --------------------------------------------------------------------- |
| App id     | `fian_app_`     | Your server's environment, as `FIANTO_APP_ID` for the SDK and CLI     |
| App secret | `fian_sk_live_` | Your server's environment, as `FIANTO_APP_SECRET`. Never in a browser |

The secret starts with `fian_sk_live_` on every deployment, devnet included. The prefix does not tell
you which cluster the key belongs to.

#### curl

`curl --user` builds the Basic header from `app_id:app_secret` for you.

```bash
curl https://api.fianto.xyz/v1/application \
  --user "$FIANTO_APP_ID:$FIANTO_APP_SECRET"
```

#### SDK

```ts
import { Fianto } from '@fianto/sdk';

// Reads FIANTO_APP_ID and FIANTO_APP_SECRET from the environment.
const fianto = new Fianto();

const application = await fianto.application.retrieve();
console.log(application);
```

## When authentication fails [#when-authentication-fails]

Every credential problem gets the same answer: a malformed header, an unknown, revoked or expired
secret, a disabled application, or a merchant account that is not approved and active. Fianto does not
say which one it was.

```text
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="fianto"
```

```json
{
  "statusCode": 401,
  "error": "Unauthorized",
  "code": "invalid_api_credentials",
  "message": "Invalid API credentials. Send \"Authorization: Basic base64(app_id:app_secret)\".",
  "request_id": "req_…"
}
```

In the SDK this is an `AuthenticationError`.

> **Credentials stop working when the account does:**
>
> Your keys work only while your merchant account is approved and active. If it is not, for example
> after an admin deactivates it, every v1 request answers 401 `invalid_api_credentials`, even
> with the right secret.

## Applications [#applications]

* A merchant can have up to 10 active applications and 100 in total.
* Creating an application needs your password, plus your two-factor code. Its secret is shown once:
  copy it straight away.

## Roll a secret [#roll-a-secret]

Roll a secret in the dashboard, for example when it may have leaked. Rolling needs your
password and two-factor code, and shows the new secret once.

You choose when the current secret stops working: immediately, in 1 hour (preselected) or in
24 hours. Until then, both secrets work, so you can deploy the new one before the old one stops. At
most two secrets are valid at a time.

> **Rolling immediately breaks every server still on the old secret:**
>
> With "Immediately", requests that send the old secret fail with 401 as soon as the roll
> finishes. Pick a grace period unless the old secret has leaked.

## Disable an application [#disable-an-application]

Disabling an application is permanent. It revokes its secrets, disables its webhook endpoint and
cancels its pending webhook deliveries. To connect again, create a new application.

## See also [#see-also]

- [API overview](/developers/overview): Base URL, endpoints and what each application sees.

- [Errors](/developers/errors): The error body, request ids and the SDK's error classes.

- [Testing](/developers/testing): Try your integration without a separate set of keys.