Skip to main content
Trade and Analytics API requests use HMAC-SHA256 authentication. Each credential contains a public API key and a secret. Send the public key, timestamp and request signature; keep the secret in your server environment.

Getting your API key

  1. Create an account or log in to the Bravado Console, your developer dashboard.
  2. Open your product under Endpoints, then API keys.
  3. Create a credential using your organisation’s enabled access. Save the secret when it is revealed; it is shown once.
  4. Set BRAVADO_API_KEY and BRAVADO_API_SECRET in your server environment.
Your organisation is created at first sign-in if you have no membership. Eligible invitations are accepted first. Plan changes apply to that organisation; they do not create a second one.

Making authenticated requests

Send these headers:
The signed payload is four fields joined with newline characters, with no final newline:
Canonicalize the path and query using the API signing rules: query keys are sorted lexicographically and values URL-encoded. Hash an empty body for a bodyless GET. For JSON writes, serialize once, hash that string and send those exact bytes. Sign the venue alias path when using /v2/trade/predictfun/... or /v2/trade/polymarket/.... See request signing examples for reusable Python and Node.js helpers. The Trade quickstart includes a complete, dependency-free Python example for a signed account read. The Console quickstart also provides TypeScript and cURL. Static Bearer authentication is a legacy, deployment-gated fallback for selected per-user reads. It is not the integration contract for new clients and does not authorize Trade mutations or master-key requests.

API key scopes

Every Bravado API key is issued with one or more scopes. A request to an endpoint that requires a scope your key doesn’t hold will be rejected with a 403 Forbidden response.
Data API requests are HMAC-signed, not Bearer-authenticated: send X-BRAVADO-API-KEY, X-BRAVADO-TIMESTAMP, and X-BRAVADO-SIGNATURE as described in Data API authentication. Each request’s venue (Polymarket, or Predict.fun under /predict/*) must also be enabled on your partner account. Bravado-issued static bearer tokens for the Data API are deprecated and only work during the migration window.
Scopes are additive, a key can hold any combination. Available scopes depend on your organisation’s access. Manage credentials in the Console. Creating an endpoint does not grant additional scopes.

Master keys vs. user keys

Bravado supports two key archetypes that serve different purposes in a partner integration: Master keys are issued at the partner level. They are not bound to a specific user wallet. A master key with the trade.users scope can call the user provisioning endpoints to create and manage sub-accounts on behalf of your platform. Use a master key in your backend services, never expose it to end users. Per-user keys are bound to a specific provisioned user wallet. All trade activity executed with a per-user key is attributed to that wallet. These keys typically hold trade.read, trade.execute, and trade.cancel scopes, but not trade.users. Use your master key to provision users and generate their keys. Use per-user keys to execute trades on their behalf.

MCP server authorization

The MCP server does not take an API key. It uses OAuth 2.1 with PKCE, and access is granted by a human approving a consent screen rather than by pasting a secret into a client. Why it differs from the rest of the API:
  • An MCP client runs on someone’s laptop or in a chat product. Handing it a partner master key would put a credential that can act for your whole organisation somewhere you cannot rotate or audit.
  • Data API requests are HMAC-signed. An MCP client has no way to compute that signature, and giving it the secret to do so would defeat the point of signing.
The flow, from the client’s point of view:
  1. It reads https://mcp.bravadotrade.com/.well-known/oauth-protected-resource to find the authorization server.
  2. It registers itself (RFC 7591 Dynamic Client Registration). Registering grants nothing on its own.
  3. It opens the discovered Bravado authorization endpoint for sign-in and consent. Start setup from MCP in the Console.
  4. It receives a short-lived access token plus a rotating refresh token.
Tokens are scoped to mcp.read and mcp.query — the MCP Server product, which is separate from the Data API — and bound to the organisation you approve in Console. They are audience-bound to the MCP server, so a token issued for it cannot be replayed against any other Bravado surface. Revoke a connection from Connected applications in Console at any time. Revocation takes effect immediately for the refresh token; an access token already issued is stateless and expires within five minutes.

Authentication errors

Bravado returns standard HTTP status codes for authentication failures. Your client should handle these explicitly.

401 Unauthorized

Check the public key, timestamp and HMAC signature. Sign the path you actually call, include canonical query parameters, and hash the exact body bytes sent. A GET with no body hashes the empty string. Keep the client clock synchronized.

403 Forbidden

Authentication succeeded but a scope, venue entitlement or account-readiness requirement was not met. Inspect the response error code and your organisation’s access. A successful account read does not imply permission to execute or withdraw.

Idempotency keys

Every mutating request (POST, PATCH, and DELETE) requires an Idempotency-Key header. Bravado uses this key to deduplicate requests, so if a network timeout causes you to retry an operation, you won’t accidentally create a second order or cancellation.
Rules for idempotency keys:
  • Generate a fresh UUID v4 for each new intended operation.
  • Use the same key when retrying a request that failed with a network error or timeout.
  • Do not reuse a key from a previous, successfully completed request to create a new one.
  • Keys are scoped to your API token, the same UUID used by a different token is treated as a separate key.
Most HTTP client libraries have a built-in UUID generator. In Python, use str(uuid.uuid4()). In Node.js, use crypto.randomUUID(). In Go, use the github.com/google/uuid package.
If you send a retry with the same idempotency key as a request that already succeeded, Bravado returns the original response with an Idempotent-Replayed: true header, no duplicate operation is performed.