Skip to main content
Access to the Issuing API is authenticated using an API access key combined with cryptographically signed API requests.

Overview

To authenticate your implementation against the Issuing API, you must complete three steps:
  1. Generate an RSA key pair - Create a public/private RSA key pair in PEM format (minimum 2048 bits)
  2. Register your public key - Email your public key and IP whitelist address to your implementation manager. In return, you’ll receive an Access Key (UUID). In the future, this can be done via the UTGL Developer Portal.
  3. Sign your requests - Use your access key and private key to generate signed JWT tokens for each API request

Authentication Flow

The following diagram illustrates the complete authentication flow from initial setup to making authenticated API requests:

Step 1: Generate RSA Key Pair

Generate a public/private RSA key pair using OpenSSL or your preferred tool.
Security Warning: Ensure your private key is stored in a secure, encrypted location and never expose it to anyone.Gaining access to your access key + private key essentially grants full access to your account.
openssl req -new -newkey rsa:4096 -nodes \
	-keyout utgl-access.private -out utgl-access.csr

Step 2: Create Bearer Token

Each API request requires a Bearer token in the Authorization header. The token is a signed JWT that includes request-specific claims.

Process Overview

  1. Create the JWT header and payload - Include required claims (URI, method, body hash, etc.)
  2. Sign the JWT - Use your RSA private key with the RS256 algorithm
  3. Add to request header - Include the signed token as Authorization: Bearer <token>
The Issuing API verifies the JWT signature against the provided claims and validates the URI, method, and request body against the claims.

JWT Creation Process

If token verification fails, the API returns HTTP 401 Unauthorized with error code INVALID_SIGNATURE.

JWT Token Specification

The JWT token must be created according to the following specification. The JWT header must contain:
FieldValueDescription
algRS256Signature algorithm
typJWTToken type

Payload (Claims)

The JWT payload must include the following claims:
ClaimRequiredDescriptionExample
subYesYour Access Key (UUID)899a7a89-bb6b-4d43-a702-c6aa45dd89cf
iatYesIssued at time (Unix timestamp in seconds)1668849961
expYesExpiration time (Unix timestamp in seconds). Must be less than iat + 30 seconds1668849991
bodyConditionalHex-encoded SHA-256 hash of the raw HTTP request body. Optional for GET requests (empty body)93a23971a914e5eacbf0a8d25154cda309c3c1c72fbb9914d47c60f3cb681588
uriYesThe URI part of the request, including query parameters/v1/transactions?filter=123
methodYesThe HTTP method of the requestGET, POST, PUT, DELETE

Signing

The JWT must be signed using your RSA Private Key with the RS256 algorithm.
Implementation Examples: See our language-specific guides for complete implementation examples:

Example: GET Request

The following example demonstrates how to create a JWT for a GET request to /ping.

Test Credentials

6e33a078-99ed-4aa1-8e67-b0e19e9475fd

JWT Components

{
  "alg": "RS256",
  "typ": "JWT"
}

Example: POST Request

The following example demonstrates how to create a JWT for a POST request with a request body.

Request Details

  • Endpoint: POST /ping
  • Request Body: {"hello":"world"}
  • Access ID: ed63e5a1-3e8e-4b63-96b5-b711f91bc2dd

JWT Components

{
  "alg": "RS256",
  "typ": "JWT"
}
Important: The body claim contains the hex-encoded SHA-256 hash of the raw request body. For POST requests, you must include this hash. The exact string representation of the body must match between signing and sending.

Common Issues & Troubleshooting

Token Expiration

JWT tokens expire after 30 seconds. Generate a fresh token for each API request.

Body Hash Mismatch

Ensure the request body used for signing exactly matches the body sent in the HTTP request. Common issues:
  • Trailing whitespace differences
  • JSON formatting differences (spaces, newlines)
  • Character encoding mismatches

Invalid Signature Errors

If you receive INVALID_SIGNATURE errors:
  1. Verify your private key is correct and properly formatted
  2. Ensure you’re using RS256 algorithm
  3. Check that all required claims are present
  4. Verify the uri includes query parameters if present
  5. Confirm the body hash matches the actual request body (for POST requests)

Next Steps