Skip to main content

Token Exchange Endpoint

Exchange a signed JWT assertion for a platform access token.

Endpoint

POST https://prod.rynopay.io/auth/partner/v1/token

Request body

FieldTypeRequiredDescription
grantTypestringYesMust be urn:ietf:params:oauth:grant-type:jwt-bearer
assertionstringYesECDSA-signed JWT assertion
scopestringNoSpace-separated scope list. Defaults to all granted scopes

Example request

curl -X POST https://prod.rynopay.io/auth/partner/v1/token \
-H "Content-Type: application/json" \
-d '{
"grantType": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMzQ1...",
"scope": "partner.read partner.write"
}'

Response

200 OK

{
"accessToken": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 3600,
"scope": "partner.read partner.write"
}
FieldTypeDescription
accessTokenstringPlatform-signed JWT access token
tokenTypestringAlways Bearer
expiresInintegerToken lifetime in seconds
scopestringSpace-separated list of granted scopes

400 Bad Request

{
"isSuccess": false,
"error": {
"code": "TokenExchange.InvalidSignature",
"message": "JWT assertion signature validation failed"
}
}

See Error Reference for all error codes.

JWT assertion requirements

The assertion field must be a valid JWT with:

{
"alg": "ES256",
"typ": "JWT",
"kid": "<api-key-id>"
}

Payload

{
"iss": "<partner-id>",
"sub": "<partner-id>",
"aud": "https://prod.rynopay.io/auth/partner/v1/token",
"iat": 1700000000,
"exp": 1700000300,
"jti": "<unique-id>"
}

Validation rules

RuleRequirement
AlgorithmES256
kidMust be a valid UUID matching a registered API key
issMust be the Partner ID associated with the API key
subMust equal iss
audMust be https://prod.rynopay.io/auth/partner/v1/token
exp - iatMust not exceed 300 seconds (5 minutes)
jtiMust be unique (replay prevention via server-side cache)
SignatureMust be valid against the registered public key
API keyMust not be expired
Partner accountMust be active