Authorization: Bearer <your-access-token>. Each OAuth record has its own token cache, so your authorization server sees far fewer token requests than deliveries.
Credentials live in one object, an OAuth record. Create it once, attach it to as many webhooks as you need, and rotate the secret in a single call.
Availability: OAuth 2.0 for webhooks is available to Enterprise customers and above. Contact your Customer Success Manager to enable it for your workspace.
How it works
- Your authorization server issues access tokens. Fireblocks calls it the token endpoint.
- Your receiver is the endpoint the webhook is delivered to, and the thing that wants a bearer token.
- An OAuth record holds the client ID, secret, and token endpoint. Create it on its own, then point a webhook at it with
webhookOauthId.
Authorization header.
Before you start
Check that each of these holds, because OAuth can’t work for your receiver until they do:- OAuth is enabled for your workspace. Ask your Customer Success Manager.
- Your token endpoint is public. It must use HTTPS on port 443, with a hostname that resolves in public DNS to a public address, so an endpoint on a private network or behind a VPN can’t be reached.
- Your authorization server supports the client credentials grant. It’s the only grant Fireblocks uses.
- Your client uses a supported authentication method, which is
client_secret_basic,client_secret_post, orclient_secret_jwt. Assertions signed with an asymmetric key (private_key_jwt) aren’t supported yet. - Your tokens are valid for more than 15 seconds. Fireblocks recommends 5 minutes. See Token lifetime.
Choose an authentication method
SetauthMethod to match how your client is registered on your authorization server. It defaults to client_secret_basic, and a mismatch returns 401 from your authorization server. Each method sends the same form-encoded POST with grant_type=client_credentials, and places the credentials differently.
client_secret_basic sends the credentials in an HTTP Basic header. Use it when your authorization server expects basic authentication:
client_secret_post sends them in the form body. Use it when your authorization server expects client_id and client_secret as body parameters:
client_secret_jwt sends a short-lived JWT signed with your client secret, so the secret itself is never transmitted. Use it when your authorization server expects a client assertion:
Quick start
1. Create an OAuth record
Call Create OAuth credentials:id, because you attach it to a webhook next. The endpoint accepts an optional Idempotency-Key header if you want a retried create to be safe.
2. Attach it to a webhook
SetwebhookOauthId on Create a new webhook, or on an existing one with Update webhook:
webhookOauthId to as many webhooks as you need. To stop sending a bearer token on one webhook without affecting the others, set webhookOauthId to null on that webhook.
A webhook with an OAuth record attached can’t also have an authorization custom header, because Fireblocks sets that header itself from the record, so a request that would leave both in place is rejected. One request can remove the header and attach the record together, so switching from a static credential to OAuth needs no intermediate step.
3. What your receiver sees
Deliveries for that webhook now carry one extra header:Optional token request parameters
Four optional fields extend the token request beyond what Create OAuth credentials requires:customBodyParamsadds parameters to the token request body with everyauthMethod, such as ascope,audience, orresourceyour authorization server expects.customJwtClaimsadds claims inside the signed assertion and is read only byclient_secret_jwt. Fireblocks setsaud,iss,sub,jti,iatandexpin every assertion. You can overrideaud; otherwise it is your token endpoint URL. The other five can’t be overridden, and setting one is refused with400.customHeadersadds a static header your authorization server’s gateway requires. It applies to the token request only, so for headers on the webhook delivery itself use the webhook’s own custom headers. Header names are stored and sent lowercased. You can setauthorizationhere only withclient_secret_postorclient_secret_jwt, because withclient_secret_basicthe credentials are that header.webhookMtlsIdpoints the token request at an mTLS record, so Fireblocks presents that record’s client certificate to your authorization server. It can be the same mTLS record your webhook uses, and it requires webhook mTLS to be enabled for your workspace. See mTLS on the token request.
Your authorization server
Token lifetime
Your authorization server has to issue tokens valid for more than 15 seconds. A webhook delivery times out after 15 seconds, so a token with less time left could lapse mid-request while your endpoint is still processing the delivery. Fireblocks doesn’t use a token with less than that remaining, so a shorter lifetime fails every delivery without a retry. The failure doesn’t name the lifetime as the cause, and from your authorization server’s side the token request succeeded. Fireblocks recommends a token lifetime of 5 minutes. The 15-second floor is not a target, because a lifetime near it means a token request on almost every delivery and no margin for a slow one.Allowlisting Fireblocks
Token requests are sent from the same IP addresses as webhook deliveries, so your existing webhook IP allowlist covers your authorization server too.Manage OAuth records
Reads return every field except
clientSecret, and names only for the three maps. Keep your own record of the values you set.
Creating, updating, and deleting an OAuth record requires the Owner, Admin, or Non-Signing Admin role. Reading is open to every role, so keep secrets out of key names, because any member of the workspace can see client IDs, token endpoint URLs, and custom key names.
Update is a partial change, so a field you omit is left as stored. name, clientId, clientSecret, url and authMethod can’t be cleared, so sending one of them as null is refused with 400. The three maps merge key by key, which means a key with a value is added or updated, a key sent as null is removed, and the whole field sent as null clears the map. Rotate the secret by sending only the new one, and the next delivery for every webhook attached to the OAuth record uses it:
409 Conflict, and the response names those webhooks. Detach them first, or pass forceDelete=true to detach them and delete the record in one call. The response lists the detached webhook IDs, and those webhooks keep delivering without an Authorization header.
Troubleshooting
For the exact status and error codes on the OAuth record endpoints themselves, see Create OAuth credentials and Update OAuth credentials.