Overview
Before making any authenticated API calls, you need to generate an API key. This is a two-step process:
- Request a challenge message from the API
- Sign the challenge with your wallet and exchange it for an API key
You’ll need one of the wallets registered with your partner account (executive authority, update authority, or withdrawal authority) to sign the challenge. The scope of the generated API key is determined by which wallet you use — see API Key Scopes below.
Step 1: Request a Challenge
Call the challenge endpoint with your wallet address and key type.
The challenge expires in 2 minutes. Complete the signing and key creation before it expires.
Your partnerId can be found on the partner dashboard on the Account page.
curl -X POST https://oro-tradebook-devnet.up.railway.app/api/auth/challenge \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "YourSolanaWalletAddress",
"keyType": "PARTNER",
"partnerId": "1"
}'
{
"success": true,
"data": {
"challengeId": "abc123-def456",
"message": "Sign this message to generate an API key for Oro Gold TradeBook: abc123-def456",
"expiresAt": "2024-01-15T10:30:00.000Z"
}
}
Use the challengeId and message from the response in the next two steps.
Step 2: Sign the Challenge
Sign the challenge message with your wallet’s private key. This proves you control the wallet.
This is a plain Ed25519 message signature — not a Solana transaction. There is no versioned or legacy transaction involved in the authentication flow.
The signing step below uses @solana/web3.js as an example, but it is not required. You can sign the challenge message using any Ed25519 signing library in your language of choice. For subsequent transaction signing, Oro provides a POST /api/transactions/submit endpoint — you only need to sign the serialized transaction bytes and submit the base64-encoded result.
import { Keypair } from "@solana/web3.js";
import nacl from "tweetnacl";
// Load your partner wallet keypair (executive, update, or withdrawal authority)
const keypair = Keypair.fromSecretKey(/* your secret key bytes */);
// The message from Step 1
const message = "Sign this message to generate an API key for Oro Gold TradeBook: abc123-def456";
const messageBytes = new TextEncoder().encode(message);
// Sign the message
const signatureBytes = nacl.sign.detached(messageBytes, keypair.secretKey);
const signature = Buffer.from(signatureBytes).toString("base64");
console.log("Signature:", signature);
Step 3: Create the API Key
Submit the challenge ID and signature to create your API key.
curl -X POST https://oro-tradebook-devnet.up.railway.app/api/auth/api-key \
-H "Content-Type: application/json" \
-d '{
"challengeId": "abc123-def456",
"signature": "your-base64-signature",
"keyName": "My Trading Key"
}'
{
"success": true,
"data": {
"apiKey": "uuid-api-key-value",
"id": "uuid-api-key-value",
"scope": ["PARTNER_EXECUTIVE_AUTHORITY"],
"name": "My Trading Key",
"walletAddress": "YourSolanaWalletAddress",
"createdAt": "2024-01-15T10:30:00.000Z"
}
}
The apiKey value is only shown once. Store it securely — you cannot retrieve it later.
Step 4: Verify Your Setup
Confirm everything works by fetching your partner details.
curl -X GET https://oro-tradebook-devnet.up.railway.app/api/distribution/partner/me \
-H "x-api-key: your-api-key"
{
"success": true,
"data": {
"partnerId": "1",
"name": "Acme Gold Trading",
"description": "Acme Gold Trading Partner",
"contactEmail": "admin@acme.com",
"kind": "SelfCustody",
"adminWalletAddress": "UpdateAuthorityWalletAddress",
"executiveAuthorityAddresses": ["WalletAddress1"],
"withdrawalAuthorityAddress": "WalletAddress3",
"centralVaultAddress": "PDAAddress123",
"createdAt": "2024-01-15T10:30:00.000Z"
}
}
Key fields to note:
kind (Custodial or SelfCustody) — determines signing requirements for all subsequent operations
centralVaultAddress — your partner’s treasury PDA
adminWalletAddress — your update authority wallet (used for partner settings and key management)
executiveAuthorityAddresses — wallets authorized for trading operations
withdrawalAuthorityAddress — wallet authorized for fund withdrawals
API Key Scopes
The scope assigned to your API key depends on which wallet you used to sign the challenge:
| Scope | Wallet | Permissions |
|---|
PARTNER_EXECUTIVE_AUTHORITY | Executive authority wallet | Trading (buy, sell), user creation |
PARTNER_UPDATE_AUTHORITY | Update authority wallet | Partner settings, key management |
PARTNER_WITHDRAWAL_AUTHORITY | Withdrawal authority wallet | Fund withdrawals |
ADMIN | Admin wallet | System administration |
Create separate API keys for different operations. Use an executive authority key for trading and a withdrawal authority key for treasury management.
Managing API Keys
List All Keys
Actual API key values are never returned — only metadata. This endpoint requires PARTNER_UPDATE_AUTHORITY scope.
curl -X GET https://oro-tradebook-devnet.up.railway.app/api/auth/api-keys \
-H "x-api-key: your-api-key"
{
"success": true,
"data": [
{
"id": "key-uuid-1",
"name": "Trading Key",
"scope": ["PARTNER_EXECUTIVE_AUTHORITY"],
"walletAddress": "WalletAddress123",
"partnerId": 1,
"createdAt": "2024-01-15T10:30:00.000Z"
}
]
}
Revoke a Key
curl -X POST https://oro-tradebook-devnet.up.railway.app/api/auth/api-keys/key-uuid-1/revoke \
-H "x-api-key: your-api-key"
{
"success": true,
"data": {
"keyId": "key-uuid-1",
"keyName": "Trading Key",
"revokedAt": "2024-01-15T12:00:00.000Z"
}
}
Revocation is permanent and immediate. Any request using the revoked key will return 401 Unauthorized.
Next Steps
With your API key ready, proceed to Creating & Managing Users to onboard your first user.