# Create an API account. The response contains your secret key, once: it goes to olympex.env, never to the terminal.
# Needs curl, jq and OLYMPEX_PASSPHRASE in the environment. To set it without echo:
# read -rs OLYMPEX_PASSPHRASE && export OLYMPEX_PASSPHRASE
# jq builds the body from the environment, so the passphrase is JSON-escaped and never appears in a command line.
( umask 077
OLYMPEX_ACCOUNT_NAME="acme-trading-desk" jq -n '{name: env.OLYMPEX_ACCOUNT_NAME, password: env.OLYMPEX_PASSPHRASE}' |
curl -sS -X POST "https://api-rest.olympex.io/api/v1/accounts" \
-H "content-type: application/json" \
--data-binary @- -o olympex-account.json )
# Move the two values to a new olympex.env, readable only by you, and print the API key ID.
if jq -e .success olympex-account.json >/dev/null; then
( umask 077; set -C
jq -r '"OLYMPEX_API_KEY_ID=\(.data.apiKey)\nOLYMPEX_SECRET_KEY=\(.data.secretKey)"' olympex-account.json > olympex.env ) &&
rm olympex-account.json && grep '^OLYMPEX_API_KEY_ID=' olympex.env
else
cat olympex-account.json; echo
fi
// Node.js 18+. Run once, from a machine you control: every successful call creates a real account.
import { existsSync, writeFileSync } from "node:fs";
const ENV_FILE = "olympex.env";
const passphrase = process.env.OLYMPEX_PASSPHRASE ?? ""; // from your password manager
if (passphrase.length < 24 || !/^[\x20-\x7E]+$/.test(passphrase) || passphrase.trim() !== passphrase) {
throw new Error("Set OLYMPEX_PASSPHRASE to 24+ printable ASCII characters with no leading or trailing spaces.");
}
// Check before creating the account: the secret key can't be fetched again if the write fails.
if (existsSync(ENV_FILE)) throw new Error(`${ENV_FILE} already exists. Move it before you create another account.`);
const response = await fetch("https://api-rest.olympex.io/api/v1/accounts", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ name: "acme-trading-desk", password: passphrase }),
signal: AbortSignal.timeout(35_000),
});
const payload = await response.json();
if (!response.ok || payload.success !== true) {
throw new Error(`${response.status} ${payload.error?.code ?? ""} ${payload.error?.message ?? payload.message ?? ""}`.trim());
}
// The secret key is shown once. Keep it out of logs: write it to a file only you can read,
// then move it into your secrets manager.
const { apiKey, secretKey } = payload.data as { apiKey: string; secretKey: string };
writeFileSync(ENV_FILE, `OLYMPEX_API_KEY_ID=${apiKey}\nOLYMPEX_SECRET_KEY=${secretKey}\n`, { mode: 0o600, flag: "wx" });
console.log(`Created API key ID ${apiKey}. Secret key written to ${ENV_FILE}.`);
# Python 3.8+. Run once, from a machine you control: every successful call creates a real account.
import os
import re
import requests
ENV_FILE = "olympex.env"
passphrase = os.environ.get("OLYMPEX_PASSPHRASE", "") # from your password manager
if len(passphrase) < 24 or not re.fullmatch(r"[\x20-\x7e]+", passphrase) or passphrase.strip() != passphrase:
raise SystemExit("Set OLYMPEX_PASSPHRASE to 24+ printable ASCII characters with no leading or trailing spaces.")
# Check before creating the account: the secret key can't be fetched again if the write fails.
if os.path.exists(ENV_FILE):
raise SystemExit(f"{ENV_FILE} already exists. Move it before you create another account.")
response = requests.post(
"https://api-rest.olympex.io/api/v1/accounts",
json={"name": "acme-trading-desk", "password": passphrase},
timeout=35,
)
payload = response.json()
if not response.ok or payload.get("success") is not True:
error = payload.get("error") or {}
raise SystemExit(f"{response.status_code} {error.get('code', '')} {error.get('message') or payload.get('message', '')}")
# The secret key is shown once. Keep it out of logs: write it to a file only you can read,
# then move it into your secrets manager.
data = payload["data"]
fd = os.open(ENV_FILE, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
with os.fdopen(fd, "w") as env_file:
env_file.write(f"OLYMPEX_API_KEY_ID={data['apiKey']}\nOLYMPEX_SECRET_KEY={data['secretKey']}\n")
print(f"Created API key ID {data['apiKey']}. Secret key written to {ENV_FILE}.")
{
"success": true,
"data": {
"message": "ACCOUNT_CREATED",
"apiKey": "00000000-0000-4000-8000-000000000000",
"secretKey": "aol_DocsTestVector_notARealSecret_000000000"
},
"meta": {
"requestId": "ENMcEjviIAMEMYg=",
"version": "v1"
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"details": [
{
"field": "name",
"message": "name is required"
},
{
"field": "password",
"message": "password is required"
}
]
},
"meta": {
"requestId": "ENUm9iggoAMEMhw=",
"version": "v1"
}
}
Accounts and authentication
Create an account
Create an API account and get the API key ID and secret key that sign your requests.
POST
https://api-rest.olympex.io/api/v1
/
accounts
# Create an API account. The response contains your secret key, once: it goes to olympex.env, never to the terminal.
# Needs curl, jq and OLYMPEX_PASSPHRASE in the environment. To set it without echo:
# read -rs OLYMPEX_PASSPHRASE && export OLYMPEX_PASSPHRASE
# jq builds the body from the environment, so the passphrase is JSON-escaped and never appears in a command line.
( umask 077
OLYMPEX_ACCOUNT_NAME="acme-trading-desk" jq -n '{name: env.OLYMPEX_ACCOUNT_NAME, password: env.OLYMPEX_PASSPHRASE}' |
curl -sS -X POST "https://api-rest.olympex.io/api/v1/accounts" \
-H "content-type: application/json" \
--data-binary @- -o olympex-account.json )
# Move the two values to a new olympex.env, readable only by you, and print the API key ID.
if jq -e .success olympex-account.json >/dev/null; then
( umask 077; set -C
jq -r '"OLYMPEX_API_KEY_ID=\(.data.apiKey)\nOLYMPEX_SECRET_KEY=\(.data.secretKey)"' olympex-account.json > olympex.env ) &&
rm olympex-account.json && grep '^OLYMPEX_API_KEY_ID=' olympex.env
else
cat olympex-account.json; echo
fi
// Node.js 18+. Run once, from a machine you control: every successful call creates a real account.
import { existsSync, writeFileSync } from "node:fs";
const ENV_FILE = "olympex.env";
const passphrase = process.env.OLYMPEX_PASSPHRASE ?? ""; // from your password manager
if (passphrase.length < 24 || !/^[\x20-\x7E]+$/.test(passphrase) || passphrase.trim() !== passphrase) {
throw new Error("Set OLYMPEX_PASSPHRASE to 24+ printable ASCII characters with no leading or trailing spaces.");
}
// Check before creating the account: the secret key can't be fetched again if the write fails.
if (existsSync(ENV_FILE)) throw new Error(`${ENV_FILE} already exists. Move it before you create another account.`);
const response = await fetch("https://api-rest.olympex.io/api/v1/accounts", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ name: "acme-trading-desk", password: passphrase }),
signal: AbortSignal.timeout(35_000),
});
const payload = await response.json();
if (!response.ok || payload.success !== true) {
throw new Error(`${response.status} ${payload.error?.code ?? ""} ${payload.error?.message ?? payload.message ?? ""}`.trim());
}
// The secret key is shown once. Keep it out of logs: write it to a file only you can read,
// then move it into your secrets manager.
const { apiKey, secretKey } = payload.data as { apiKey: string; secretKey: string };
writeFileSync(ENV_FILE, `OLYMPEX_API_KEY_ID=${apiKey}\nOLYMPEX_SECRET_KEY=${secretKey}\n`, { mode: 0o600, flag: "wx" });
console.log(`Created API key ID ${apiKey}. Secret key written to ${ENV_FILE}.`);
# Python 3.8+. Run once, from a machine you control: every successful call creates a real account.
import os
import re
import requests
ENV_FILE = "olympex.env"
passphrase = os.environ.get("OLYMPEX_PASSPHRASE", "") # from your password manager
if len(passphrase) < 24 or not re.fullmatch(r"[\x20-\x7e]+", passphrase) or passphrase.strip() != passphrase:
raise SystemExit("Set OLYMPEX_PASSPHRASE to 24+ printable ASCII characters with no leading or trailing spaces.")
# Check before creating the account: the secret key can't be fetched again if the write fails.
if os.path.exists(ENV_FILE):
raise SystemExit(f"{ENV_FILE} already exists. Move it before you create another account.")
response = requests.post(
"https://api-rest.olympex.io/api/v1/accounts",
json={"name": "acme-trading-desk", "password": passphrase},
timeout=35,
)
payload = response.json()
if not response.ok or payload.get("success") is not True:
error = payload.get("error") or {}
raise SystemExit(f"{response.status_code} {error.get('code', '')} {error.get('message') or payload.get('message', '')}")
# The secret key is shown once. Keep it out of logs: write it to a file only you can read,
# then move it into your secrets manager.
data = payload["data"]
fd = os.open(ENV_FILE, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
with os.fdopen(fd, "w") as env_file:
env_file.write(f"OLYMPEX_API_KEY_ID={data['apiKey']}\nOLYMPEX_SECRET_KEY={data['secretKey']}\n")
print(f"Created API key ID {data['apiKey']}. Secret key written to {ENV_FILE}.")
{
"success": true,
"data": {
"message": "ACCOUNT_CREATED",
"apiKey": "00000000-0000-4000-8000-000000000000",
"secretKey": "aol_DocsTestVector_notARealSecret_000000000"
},
"meta": {
"requestId": "ENMcEjviIAMEMYg=",
"version": "v1"
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"details": [
{
"field": "name",
"message": "name is required"
},
{
"field": "password",
"message": "password is required"
}
]
},
"meta": {
"requestId": "ENUm9iggoAMEMhw=",
"version": "v1"
}
}
POST /accounts creates an API account and returns its API key ID (apiKey) and secret key (secretKey). The password you send becomes the account’s passphrase. You sign every request to the signed endpoints with these three values, as described in Sign requests. This endpoint is public: it takes no signed headers.
What you get back
| Credential | Where it comes from | How you use it | Environment variable |
|---|---|---|---|
| API key ID | data.apiKey, a UUID | Sent as x-api-key-id on every signed request. | OLYMPEX_API_KEY_ID |
| Secret key | data.secretKey, a random string shown once | The HMAC key for x-signature, used as the string itself: don’t decode it or check its format. You never send it. | OLYMPEX_SECRET_KEY |
| Passphrase | The password you sent | Sent as x-passphrase on every signed request. | OLYMPEX_PASSPHRASE |
Choose the passphrase
- Use at least 24 random characters from a password manager. The API accepts 8 or more, but the passphrase guards your account as much as the secret key does.
- Use printable ASCII only, with no leading or trailing spaces. The API trims the
x-passphraseheader, and browsers can’t send characters outside ISO-8859-1. A passphrase with leading or trailing spaces, or with characters a client can’t send in a header, creates an account you can’t sign requests for. Printable ASCII avoids both. - Protect it like the secret key. Every signed request carries it in
x-passphrase, so anything that logs request headers can capture it. nameis only a label. It needs at least 6 characters, and names don’t have to be unique.
name shorter than 6 characters or a password shorter than 8 fails with 400 VALIDATION_ERROR, and the detail reads "name is required" or "password is required" even when the field is present.
Store the credentials right away
The secret key appears in this response and nowhere else. Olympex stores only a hash of the passphrase and an encrypted copy of the secret key, and no endpoint returns either one again. Write all three values to your secrets manager before you do anything else, and keep the response out of logs, tickets and chat. The200 example on this page shows the API key ID and the secret key of the known-answer vectors, which are test values, not a real account. Your secret key is a different random string.
Credentials can’t be rotated or changed after you create them. If any of the three values leaks, email partners@olympex.io to deactivate the account, then create a new one and switch your integration to it.
Test and production accounts
The console on this page creates a real account with a passphrase generated in your browser. Use it to try the API. If your browser blocks the call, use the cURL example on this page or create a key from a terminal. For production, create a separate account from a machine you control, with a passphrase from your password manager, and load the credentials from your secrets manager at runtime. There is no sandbox: both accounts call the same production API. Limit orders and DCA strategies created with either account are real orders, and only the account that created them can read, change or cancel them. Going to production has the full checklist.Every successful call creates a new account. If a request fails before you read the response, an account may already exist whose secret key you never saw. Create another one by hand (names don’t have to be unique), and never retry this call automatically.
# Create an API account. The response contains your secret key, once: it goes to olympex.env, never to the terminal.
# Needs curl, jq and OLYMPEX_PASSPHRASE in the environment. To set it without echo:
# read -rs OLYMPEX_PASSPHRASE && export OLYMPEX_PASSPHRASE
# jq builds the body from the environment, so the passphrase is JSON-escaped and never appears in a command line.
( umask 077
OLYMPEX_ACCOUNT_NAME="acme-trading-desk" jq -n '{name: env.OLYMPEX_ACCOUNT_NAME, password: env.OLYMPEX_PASSPHRASE}' |
curl -sS -X POST "https://api-rest.olympex.io/api/v1/accounts" \
-H "content-type: application/json" \
--data-binary @- -o olympex-account.json )
# Move the two values to a new olympex.env, readable only by you, and print the API key ID.
if jq -e .success olympex-account.json >/dev/null; then
( umask 077; set -C
jq -r '"OLYMPEX_API_KEY_ID=\(.data.apiKey)\nOLYMPEX_SECRET_KEY=\(.data.secretKey)"' olympex-account.json > olympex.env ) &&
rm olympex-account.json && grep '^OLYMPEX_API_KEY_ID=' olympex.env
else
cat olympex-account.json; echo
fi
// Node.js 18+. Run once, from a machine you control: every successful call creates a real account.
import { existsSync, writeFileSync } from "node:fs";
const ENV_FILE = "olympex.env";
const passphrase = process.env.OLYMPEX_PASSPHRASE ?? ""; // from your password manager
if (passphrase.length < 24 || !/^[\x20-\x7E]+$/.test(passphrase) || passphrase.trim() !== passphrase) {
throw new Error("Set OLYMPEX_PASSPHRASE to 24+ printable ASCII characters with no leading or trailing spaces.");
}
// Check before creating the account: the secret key can't be fetched again if the write fails.
if (existsSync(ENV_FILE)) throw new Error(`${ENV_FILE} already exists. Move it before you create another account.`);
const response = await fetch("https://api-rest.olympex.io/api/v1/accounts", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ name: "acme-trading-desk", password: passphrase }),
signal: AbortSignal.timeout(35_000),
});
const payload = await response.json();
if (!response.ok || payload.success !== true) {
throw new Error(`${response.status} ${payload.error?.code ?? ""} ${payload.error?.message ?? payload.message ?? ""}`.trim());
}
// The secret key is shown once. Keep it out of logs: write it to a file only you can read,
// then move it into your secrets manager.
const { apiKey, secretKey } = payload.data as { apiKey: string; secretKey: string };
writeFileSync(ENV_FILE, `OLYMPEX_API_KEY_ID=${apiKey}\nOLYMPEX_SECRET_KEY=${secretKey}\n`, { mode: 0o600, flag: "wx" });
console.log(`Created API key ID ${apiKey}. Secret key written to ${ENV_FILE}.`);
# Python 3.8+. Run once, from a machine you control: every successful call creates a real account.
import os
import re
import requests
ENV_FILE = "olympex.env"
passphrase = os.environ.get("OLYMPEX_PASSPHRASE", "") # from your password manager
if len(passphrase) < 24 or not re.fullmatch(r"[\x20-\x7e]+", passphrase) or passphrase.strip() != passphrase:
raise SystemExit("Set OLYMPEX_PASSPHRASE to 24+ printable ASCII characters with no leading or trailing spaces.")
# Check before creating the account: the secret key can't be fetched again if the write fails.
if os.path.exists(ENV_FILE):
raise SystemExit(f"{ENV_FILE} already exists. Move it before you create another account.")
response = requests.post(
"https://api-rest.olympex.io/api/v1/accounts",
json={"name": "acme-trading-desk", "password": passphrase},
timeout=35,
)
payload = response.json()
if not response.ok or payload.get("success") is not True:
error = payload.get("error") or {}
raise SystemExit(f"{response.status_code} {error.get('code', '')} {error.get('message') or payload.get('message', '')}")
# The secret key is shown once. Keep it out of logs: write it to a file only you can read,
# then move it into your secrets manager.
data = payload["data"]
fd = os.open(ENV_FILE, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
with os.fdopen(fd, "w") as env_file:
env_file.write(f"OLYMPEX_API_KEY_ID={data['apiKey']}\nOLYMPEX_SECRET_KEY={data['secretKey']}\n")
print(f"Created API key ID {data['apiKey']}. Secret key written to {ENV_FILE}.")
{
"success": true,
"data": {
"message": "ACCOUNT_CREATED",
"apiKey": "00000000-0000-4000-8000-000000000000",
"secretKey": "aol_DocsTestVector_notARealSecret_000000000"
},
"meta": {
"requestId": "ENMcEjviIAMEMYg=",
"version": "v1"
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"details": [
{
"field": "name",
"message": "name is required"
},
{
"field": "password",
"message": "password is required"
}
]
},
"meta": {
"requestId": "ENUm9iggoAMEMhw=",
"version": "v1"
}
}
Body
application/json
Label for the account, at least 6 characters. Names don't have to be unique.
Minimum string length:
6Example:
"acme-trading-desk"
Becomes the account passphrase, sent as x-passphrase on every signed request. Use at least 24 random printable-ASCII characters with no leading or trailing spaces: the API trims the header, and browsers can't send characters outside ISO-8859-1, so other values create an account you can't use.
Minimum string length:
8Was this page helpful?
