Skip to main content

Overview

Before making any authenticated API calls, you need to generate an API key. This is a two-step process:
  1. Request a challenge message from the API
  2. 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:
ScopeWalletPermissions
PARTNER_EXECUTIVE_AUTHORITYExecutive authority walletTrading (buy, sell), user creation
PARTNER_UPDATE_AUTHORITYUpdate authority walletPartner settings, key management
PARTNER_WITHDRAWAL_AUTHORITYWithdrawal authority walletFund withdrawals
ADMINAdmin walletSystem 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.