Telephony Integration REST API Authorization for Agentforce Voice

Partners integrating with Agentforce Voice over SIP or Dynamic Routing authorize Telephony Integration REST API requests with a partner-signed JSON Web Token (JWT).

Salesforce verifies a partner-signed JWT on each request. You hold the private key, and you upload the matching public key to the Agentforce Voice channel that you own. There's no client secret and no OAuth exchange. A signed JWT is the bearer token.

To authorize your requests, set up an Agentforce Voice channel and register your public key, and then mint and send a signed JWT on each request.

If you're integrating a call center or Service Cloud Voice contact center instead of Agentforce Voice, see Telephony Integration REST API Authorization.

Set Up an Agentforce Voice Channel and Register Your Public Key

Before you mint a JWT, set up an Agentforce Voice channel and register your public key.

  1. From Setup, in the Quick Find box, enter Partner Telephony Setup, and then select Partner Telephony Setup.
  2. Click New Channel to create a new channel, and select Agentforce Voice (AFV)—SIP / Dynamic Routing as the channel type.
  3. Choose a Channel Name, the developer-facing API name, not the display label.

    The name must be alphanumeric with underscores only, must be unique within the org, and can't be renamed after creation. For example, acme_voice_prod.

    Salesforce stores the channel name on the underlying record as channelDeveloperName. This is the exact value that you put in the sub claim of every JWT that you sign for this channel. Salesforce uses channelDeveloperName to look up the public key to verify the token. Note that customers see the Channel Name, not the Channel Developer Name. The two can differ.

    The sub claim is the channel developer name, not the E.164 phone number. Each channel supports a single phone number at a time. The developer name identifies the channel, and the signing key you use is scoped to that channel.

    Note

  4. Generate an RSA key pair and keep the private key secret. Export the public key in SubjectPublicKeyInfo (PKCS#8) armor.
    1-----BEGIN PUBLIC KEY-----
    2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
    3-----END PUBLIC KEY-----

    Only SubjectPublicKeyInfo (PKCS#8) format is supported. PKCS#1 RSA public keys and X.509 certificates aren't supported for this channel type. An X.509 certificate is the call center or Service Cloud Voice path, not Agentforce Voice. Never upload a private key.

  5. Open the channel and go to Channel Setup and click Authentication, paste the public key into the Public Key field, and then click Save.

    Channel detail page with the Public Key field under Messaging Settings

    You can update the public key at any time to rotate it. The new key takes effect within a few minutes as caches expire. Rotate the public key at least annually.

  6. Mint and send a signed JWT.

Mint and Send a Signed JWT

After your channel and public key are in place, mint a JWT for each request and send it as a bearer token.

  1. Construct a JSON claims set for the JWT.
    Claim Required Value
    iss Yes Your Salesforce org ID (18-character).
    sub Yes The channel name you chose during setup (channelDeveloperName).
    iat Yes Issued-at time, in seconds since the Unix epoch.
    exp Yes Expiry, in seconds since the Unix epoch. Unlike the call center or Service Cloud Voice JWT, this expiration isn't capped at 24 hours. Choose a lifetime that matches your key-rotation policy. We recommend short-lived tokens (minutes to a few hours) minted per call or per session.
    roles Yes The literal string voiceagent. This private body claim is how Salesforce recognizes the token as an Agentforce Voice partner token and routes it to the Agentforce Voice public-key lookup. Any other value, or an absent claim, is treated as a call center or Service Cloud Voice token, fails key lookup, and returns a 401.

    Example claims set:

    1{
    2  "iss": "00Dxx0000001gPAEAY",
    3  "sub": "acme_voice_prod",
    4  "iat": 1785312000,
    5  "exp": 1785315600,
    6  "roles": "voiceagent"
    7}
  2. Sign the token with your private key using RS256.

    RS256 is the only signing algorithm that Salesforce accepts for this channel type.

  3. Send the signed JWT in the standard HTTP Authorization header on every request.
    1Authorization: Bearer <your-signed-jwt>

    Don't embed the private key in shipped client code or store it in a repository. Treat it like a database password.

On every request, Salesforce checks that:

  • The signing algorithm is RS256.
  • The roles claim equals voiceagent, which routes the request to the Agentforce Voice key lookup instead of the call center key lookup.
  • The channel is found by (iss, sub) and its uploaded public key is read.
  • The signature verifies against that public key.
  • The exp claim hasn't passed.

Salesforce stamps requests that pass all checks with the ROLE_AFV_PARTNER role. Only Agentforce Voice-eligible endpoints accept this role; calls to other endpoints get a 403.

Troubleshoot Authorization Errors

Use this table to diagnose common authorization failures.

Symptom Likely Cause
401 Unauthorized immediately after onboarding The roles claim is missing or isn't exactly voiceagent. Salesforce routed the request to the call center or Service Cloud Voice key store and found no key.
401 after uploading a new public key The cache still holds the old key. Wait a few minutes, or retry.
401 on tokens that verify locally The sub claim doesn't match the channel's name, or iss isn't your 18-character org ID.
403 Forbidden on a specific endpoint The endpoint isn't opted into the Agentforce Voice role. Confirm with your Salesforce contact that the endpoint accepts ROLE_AFV_PARTNER.
Invalid public key on upload The public key isn't in SubjectPublicKeyInfo (PKCS#8) armor.