Skip to main content

Create Token

Issues a signed JWT (JSON Web Token) valid for 60 minutes, containing the claims you supply plus standard claims (jti, iat, exp, iss) added by the server.

  • Issuer (iss): AccessPayHub
  • Signing algorithm: RS256 (RSA-2048)

Endpoint​

POST /token

Full production URL: https://group.pay.accessacloud.com/loader/token

Header Parameters​

ParameterTypeRequiredDescription
Content-TypestringrequiredMust be application/json
X-Api-KeystringrequiredYour issued API key

Request Parameters​

ParameterTypeRequiredDescription
claimsobjectrequiredFlat dictionary of string keys to string values. Sent verbatim into the JWT (see Claims object below)

Claims Object​

  • A flat dictionary mapping string keys to string values.
  • At least one entry is required — sending an empty claims object returns 400 Bad Request.
  • Claim names and values are passed through verbatim into the JWT, so use the exact names your downstream consumer expects (e.g. sub, org_id, role).
  • Don't send jti, iat, exp, or iss — the server sets those itself. If you include them, the server's values still take precedence.
  • Nested objects and arrays are not supported. If you need structured data, serialise it yourself (e.g. JSON-stringify into a single claim value).

Response Parameters​

Status Code: 200 OK​

ParameterTypeDescription
tokenstringThe full signed JWT

Token Contents​

When the returned JWT is decoded, it contains:

ClaimTypeDescription
(your claims)stringEvery claim you sent in the claims dictionary, exactly as sent
issstringIssuer — always AccessPayHub
jtistringUnique token GUID (anti-replay)
iatnumberUnix timestamp (seconds) when the token was issued
expnumberUnix timestamp (seconds) when the token expires (iat + 3600)
info

You can decode the token (without verifying the signature) on jwt.io to inspect the claims while developing.

Example Request​

{
"claims": {
"sub": "user-12345",
"org_id": "org-67890",
"role": "admin"
}
}

Example Response​

{
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEyMzQ1Iiwib3JnX2lkIjoib3JnLTY3ODkwIiwicm9sZSI6ImFkbWluIiwianRpIjoiOGYzMmZlMmYtYmNmMS00ZGI3LTljZTAtZGM0NWE5MWEwYjIyIiwiaWF0IjoxNzYyNTEyMDAwLCJleHAiOjE3NjI1MTU2MDAsImlzcyI6IkFjY2Vzc1BheUh1YiJ9..."
}

Decoded payload (for the example request above):

{
"sub": "user-12345",
"org_id": "org-67890",
"role": "admin",
"jti": "8f32fe2f-bcf1-4db7-9ce0-dc45a91a0b22",
"iat": 1762512000,
"exp": 1762515600,
"iss": "AccessPayHub"
}

Status Code: 400 Bad Request​

Returned when the request body is missing, malformed, or claims is empty. Make sure:

  • The body is valid JSON.
  • Content-Type: application/json is set.
  • claims has at least one entry.
{ "error": "Claims are required." }

Status Code: 401 Unauthorized​

Returned when the X-Api-Key header is missing or doesn't match a configured key. Confirm you're using the correct key and that the header name is exactly X-Api-Key.

Status Code: 503 Service Unavailable​

Returned when the server has no API keys configured at all — this is a server-side misconfiguration, not a problem with your request. Contact the platform team. Retrying won't help until config is fixed.

Usage Notes​

  • Use the returned token straight away — pass it as Authorization: Bearer <token> to downstream services that accept JWTs issued by AccessPayHub.
  • The token expires 60 minutes after issuance. Cache it if you call it often, but don't cache past exp.
  • There is no refresh endpoint — call POST /token again to get a new token.
  • Downstream services that verify the token need the matching public key. Request it from the platform team if you're integrating a verifier.

Code Samples​

In all examples below, replace <your-api-key> with the API key issued to you by the platform team.

For a cURL example, see cURL.

PowerShell​

$apiKey = "<your-api-key>"

$headers = @{
"Content-Type" = "application/json"
"X-Api-Key" = $apiKey
}

$body = @{
claims = @{
sub = "user-12345"
org_id = "org-67890"
role = "admin"
}
} | ConvertTo-Json

$response = Invoke-RestMethod `
-Uri "https://group.pay.accessacloud.com/loader/token" `
-Method Post `
-Headers $headers `
-Body $body

Write-Host "JWT: $($response.token)"

C# (HttpClient)​

using System.Net.Http.Json;

var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", "<your-api-key>");

var payload = new
{
claims = new Dictionary<string, string>
{
["sub"] = "user-12345",
["org_id"] = "org-67890",
["role"] = "admin"
}
};

var response = await http.PostAsJsonAsync(
"https://group.pay.accessacloud.com/loader/token",
payload);
response.EnsureSuccessStatusCode();

var result = await response.Content.ReadFromJsonAsync<TokenResponse>();
Console.WriteLine(result?.Token);

record TokenResponse(string Token);

JavaScript (fetch)​

const response = await fetch("https://group.pay.accessacloud.com/loader/token", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": "<your-api-key>"
},
body: JSON.stringify({
claims: {
sub: "user-12345",
org_id: "org-67890",
role: "admin"
}
})
});

if (!response.ok) {
throw new Error(`Token request failed: ${response.status}`);
}

const { token } = await response.json();
console.log(token);

FAQ​

How long is a token valid? 60 minutes from the moment it's issued (exp = iat + 3600).

Can I extend the lifetime or refresh a token? No — the lifetime is fixed server-side, and there's no refresh endpoint. Just call the endpoint again to get a new one.

Can I include nested objects or arrays in claims? No. claims is a flat dictionary of strings to strings. Both keys and values must be strings. If you need structured data, serialise it yourself (e.g. JSON-stringify into a single claim value).

What happens if I send iat, exp, or jti myself? The server adds its own values for these. The server's standard-claim values take precedence over any you provide.

Where do I get an API key? From the platform team. Keys are issued per consumer and can be rotated on request.

My request returns 401 even though I'm sure my key is right. What now? Check, in this order:

  1. The header is named exactly X-Api-Key (no X-API-KEY typo, no Authorization: prefix).
  2. There's no leading/trailing whitespace or stray quotes around the value.
  3. The key hasn't been rotated — confirm with the platform team.

How is the token signed? With RSA-2048 (RS256). Downstream services that verify the token need the matching public key — request it from the platform team if you're integrating a verifier.