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

# Credentials

> The API key ID, secret key and passphrase: what each one does, how Olympex stores it, and how to keep it safe.

An API account has three credentials. [`POST /accounts`](/api-reference/accounts/create-account) returns two of them, the API key ID and the secret key. The third is the `password` you sent in that request, which becomes your passphrase. Together they sign requests as your account, so treat all three as production secrets.

## What each credential does

| Credential | Where you get it | On signed requests |
| - | - | - |
| API key ID | `apiKey` in the `POST /accounts` response, a UUID | Sent as `x-api-key-id` |
| Secret key | `secretKey` in the same response, a random string. Shown only once. | Never sent. It is the HMAC key you sign with. |
| Passphrase | The `password` you chose in the `POST /accounts` request. Never returned. | Sent as `x-passphrase` |

### API key ID

The API key ID identifies your account. You send it in `x-api-key-id` on every signed request, and Olympex uses it to look up your account. It can't sign anything: signing needs the secret key. Keep it out of client code and public places anyway.

### Secret key

The secret key is the HMAC key you sign with: a random string, shown once. Use the string exactly as `POST /accounts` returned it, as UTF-8 bytes. Don't base64-decode it, even if it looks like base64. After the account is created, the secret key never travels over the network again. Each request carries a signature made with it, not the key itself.

Olympex stores only an encrypted copy of the secret key, and no endpoint returns it again.

### Passphrase

The passphrase is the `password` you sent to `POST /accounts`. You send it in `x-passphrase` on every signed request, and Olympex checks it along with the signature. Olympex stores only a hash of it, so it can't show it to you or recover it.

## Save them when you create the account

`POST /accounts` returns the secret key once, and never returns the passphrase, because you chose it. Save the API key ID, the secret key and the passphrase to your secrets manager before you do anything else.

No endpoint returns either one again. If you lose the secret key or the passphrase, create a new API account and move your integration to it.

<Warning>
  **Protect the passphrase like the secret key.** It travels in `x-passphrase` on every signed request, so anything that records request headers records it. Together with the secret key and the API key ID, it lets anyone call every signed endpoint as your account, including creating, changing and cancelling its limit orders and DCA strategies.
</Warning>

## Store credentials on your server

Keep the credentials in environment variables on your server, injected at runtime from a secrets manager such as AWS Secrets Manager, Google Cloud Secret Manager, HashiCorp Vault, Doppler or 1Password. Name them `OLYMPEX_API_KEY_ID`, `OLYMPEX_SECRET_KEY` and `OLYMPEX_PASSPHRASE`: the [reference implementations](/authentication/sign-requests#reference-implementations) read those names with `credentialsFromEnv()` and `credentials_from_env()`, and every example in these docs uses them.

Never put a credential in any of these places:

| Place | Why |
| - | - |
| Browser, mobile or desktop clients | Anything you ship to users' devices can be extracted from the bundle, the binary or the network traffic. Have your client call your backend, and let your backend sign and call Olympex. |
| Source repositories, including committed `.env` files | Repository history keeps a secret after you delete the file, and copies spread to forks, CI caches and laptops. |
| Logs, traces and error reports | HTTP logging often captures request headers. Redact `x-passphrase`, `x-value-info` and `x-signature` wherever you log outgoing requests, and never log the secret key. An unused set of signed headers can still be sent once, for the request it was signed for, until its timestamp is 300 seconds old. |
| AI chats, support tickets and screenshots | These are stored and shared outside your control. When you contact support, send `meta.requestId` instead. |
| HAR files | A browser network export records every request header, including `x-passphrase`. Don't share one captured with real credentials. |

## Choose a strong passphrase

The `password` you send to `POST /accounts` is your passphrase for the life of the account. There is no way to change it later, so choose it carefully:

* **Printable ASCII only**, from space to `~`. Browsers can't send header values with characters outside ISO-8859-1, so other characters can make the passphrase impossible to send.
* **No leading or trailing spaces.** The API trims the `x-passphrase` header.
* **At least 24 random characters**, generated by a password manager. The API accepts 8 characters or more, but that minimum is not a recommendation.

A passphrase that breaks the first two rules creates an account you can't use.

<Tip>
  On a server without a password manager, `openssl rand -base64 24` prints 32 random printable-ASCII characters with no spaces.
</Tip>

## No rotation, revocation or scopes

API accounts have no rotation, revocation, deletion, scope or expiry features:

* You can't change the passphrase or issue a new secret key for an existing account.
* Credentials don't expire.
* Every API account can call every signed endpoint.

To replace credentials, create a new API account and move your integration to it. Load credentials from configuration, so that switching accounts is a deploy and not a code change.

Orders don't move with you. Limit orders and DCA strategies belong to the API key that created them: a new account can't list, read, change or cancel them, and gets `404 NOT_FOUND` for their IDs. Before you retire an account, cancel its open orders and strategies with its own credentials.

## If a credential is exposed

If a secret key or a passphrase may have been exposed, act as if an attacker has them.

<Steps>
  <Step title="Stop open orders first">
    If the account has open limit orders or DCA strategies, whoever holds the exposed credentials can change them, including their prices and amounts. First set each maker wallet's allowance to the Olympex order contract to `0` for every token the orders sell: that takes effect on-chain at once and no API call can undo it. See [Order signatures and allowances](/concepts/order-authorization). Then cancel the orders you don't want to keep, with the account's own credentials, while the account is still active: after deactivation, no API key can reach them.
  </Step>

  <Step title="Ask Olympex to deactivate the account">
    Email [partners@olympex.io](mailto:partners@olympex.io) with the API key ID and ask to deactivate the account. Never include the secret key or the passphrase. Once the account is inactive, the gateway rejects its requests with `403 Forbidden`.
  </Step>

  <Step title="Create a new API account">
    Create it right away with a new passphrase. You don't need to wait for the old account to be deactivated. See [Create a test API key](/get-started/create-an-api-key#create-a-key-from-a-terminal) for creating an account from a terminal.
  </Step>

  <Step title="Deploy the new credentials">
    Replace the three values in your secrets manager and redeploy every service that signs requests.
  </Step>

  <Step title="Clean up the leak">
    Remove the exposed values from wherever they leaked: logs, tickets, chats or repository history.
  </Step>
</Steps>

## Test keys from the docs

The **Create a test API key** button, on the [Create a test API key](/get-started/create-an-api-key) page and in the [API console](/api-reference/console), calls `POST /accounts` from your browser and generates a random passphrase for you. If your browser blocks the call, [create the key from a terminal](/get-started/create-an-api-key#create-a-key-from-a-terminal) instead.

<Note>
  A test key is a real API account. It calls the same production API as any other account: `POST /swap` returns real mainnet calldata, and the limit orders and DCA strategies it creates are real orders. There is no sandbox or testnet.
</Note>

Use test keys to explore the API. They are created and held in a web page that loads analytics, so don't use them in production. Create your production account from your server, with a passphrase you generate and store in your secrets manager.

## What this means for your integration

* Save the secret key and the passphrase the moment you create the account. No endpoint returns either of them again.
* Load all three credentials from a secrets manager into server-side environment variables, and redact `x-passphrase` from logs.
* Treat the passphrase like the secret key: it travels on every signed request, so anything that logs request headers can expose it.
* Make switching accounts a configuration change, so you can answer a leak with a new account and a deploy. Orders stay with the API key that created them, so cancel them before you switch.

## Related

<CardGroup cols={2}>
  <Card title="Sign requests" icon="code" href="/authentication/sign-requests">
    The signing algorithm and reference implementations.
  </Card>

  <Card title="Create a test API key" icon="key" href="/get-started/create-an-api-key">
    Get a test API key in one click, or create one from a terminal.
  </Card>

  <Card title="Security model" icon="shield-halved" href="/concepts/security-model">
    What Olympex protects, and what you are responsible for.
  </Card>

  <Card title="Going to production" icon="list-check" href="/guides/going-to-production">
    The checklist before you send real traffic.
  </Card>
</CardGroup>


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