This guide explains how to authenticate with the Fig Markets API using the FIG identity platform.
The Fig Markets API uses OAuth2/OpenID Connect for authentication. You'll need to obtain an access token using the client credentials grant flow.
- Client ID: Your API key's client identifier
- Client Secret: Your API key's client secret
- Token Endpoint: The OAuth2 token endpoint for the appropriate environment
| Environment | Token Endpoint |
|---|---|
| Production | https://id.figmarkets.com/realms/figmarkets-api/protocol/openid-connect/token |
| Test | https://id.test.figmarkets.com/realms/figmarkets-api/protocol/openid-connect/token |
Request Access Token: Send a POST request to the token endpoint with your client credentials:
curl -X POST "https://id.test.figmarkets.com/realms/figmarkets-api/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"Response: You'll receive a JSON response containing:
{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 300, "token_type": "Bearer" }The client credentials grant does not return a refresh token; request a new access token with the same credentials instead.
expires_inis the number of seconds until the access token expires. Read it from each response rather than assuming a fixed lifetime.Use the Token: Send the access token in the
Authorizationheader of every request, asBearer <token>(the scheme is case-sensitive). Every REST request must also be signed with theX-FIG-SignatureandX-FIG-Timestampheaders; see Signing Requests.curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "X-FIG-Signature: YOUR_SIGNATURE" \ -H "X-FIG-Timestamp: YOUR_TIMESTAMP" \ "https://api.test.figmarkets.com/v1/rfq"Token Refresh: To avoid service interruptions, request a new access token before the current one expires, for example when about 20% of
expires_inremains. Use the same client credentials request as in step 1.
A WebSocket connection must authenticate with an auth message within 30 seconds of opening, and must send a heartbeat message at least every 30 seconds from the moment it opens, including before and while it authenticates.
WebSocket messages are not signed: the request signature applies to REST requests only.
There are two ways to authenticate with the Fig Markets WebSocket server:
- Using an access token obtained as described in REST API Authentication
- Using your client credentials
| Environment | WebSocket URL |
|---|---|
| Test | wss://ws.test.figmarkets.com |
| Production | wss://ws.figmarkets.com |
Connect to WebSocket: Establish a WebSocket connection to the appropriate server URL, and start sending heartbeats (step 4).
Send Authentication Message: Send a JSON-RPC authentication message with your access token or client credentials:
{ "jsonrpc": "2.0", "id": "your_request_id", "method": "auth", "params": { "token": "YOUR_ACCESS_TOKEN" } }OR
{ "jsonrpc": "2.0", "id": "your_request_id", "method": "auth", "params": { "clientId": "YOUR_CLIENT_ID", "clientSecret": "YOUR_CLIENT_SECRET" } }If you use client credentials, the server responds with a new access token, which can also be used as the bearer token in REST API requests.
If you use an existing token, the server validates it and responds with a success response.
Authentication Response: On success, the server responds with:
{ "jsonrpc": "2.0", "id": "your_request_id", "method": "auth", "result": { "success": true, "token": "new_access_token_if_provided" } }On failure, the response carries a JSON-RPC
errorinstead of aresult:{ "jsonrpc": "2.0", "id": "your_request_id", "error": { "code": -32001, "message": "Invalid token" } }The
messageisInvalid token,Invalid credentialsorAuthentication failed or required.Session Maintenance: Send a heartbeat message at least every 30 seconds:
{ "jsonrpc": "2.0", "id": "your_request_id", "method": "heartbeat" }The heartbeat responds with the time it was received, as a unix timestamp in milliseconds:
{ "jsonrpc": "2.0", "id": "your_request_id", "method": "heartbeat", "result": 1703123456789 }
WebSocket sessions are bound to the lifetime of the access token used during authentication. If your token expires, the session will be terminated. To maintain a long-lived WebSocket connection, you must refresh your token before it expires.
To refresh your token, first obtain a new access token using the client credentials flow (as described in the REST API section above), then send an auth/refresh message over the WebSocket:
{
"jsonrpc": "2.0",
"id": "your_request_id",
"method": "auth/refresh",
"params": {
"token": "YOUR_NEW_ACCESS_TOKEN"
}
}The server will validate the new token, verify it belongs to the same user as the current session, and update the session expiry:
{
"jsonrpc": "2.0",
"id": "your_request_id",
"method": "auth/refresh",
"result": {
"success": true
}
}It is recommended to refresh the token when about 20% of its lifetime remains.
- Token Expiration: WebSocket sessions are terminated when the access token expires. Use
auth/refreshto extend the session before this happens. - Heartbeat Requirement: The heartbeat clock starts when the connection opens;
authandsubscribedo not reset it. A connection with noheartbeatfor 45 seconds is closed with code1008(heartbeat not received). - Reconnection: If your WebSocket connection is lost, you will need to re-authenticate and subscribe again.
- Authentication Timeout: A connection that has not authenticated within 30 seconds of opening is closed. If
authis refused, sendauthagain with a valid token or credentials:auth/refreshonly extends a session that is already authenticated. - Failed Attempts: After 3 refused
authorauth/refreshmessages, the connection is closed with code1008(too many failed authentication attempts). Each IP address can send at most 120authandauth/refreshmessages a minute.
REST authentication and signing errors return a JSON body with code and message:
| Status | When |
|---|---|
400 | X-FIG-Timestamp is not a whole number (invalid timestamp format) |
401 | The Authorization header is missing or malformed, the token is invalid or expired, a signature header is missing or wrong, the timestamp is more than 60 seconds old or more than 60 seconds ahead of the server's clock, or the request comes from an IP address that is not whitelisted for the API key |
403 | The user who created the API key does not have a role the request requires, or has not accepted the terms and conditions |
409 | The same signature has already been accepted (request already processed); see Signing Requests |
Always check the error response body for detailed information about authentication failures.