#!/usr/bin/env bash
# Rotate a refresh token for a new access + refresh pair. The old refresh
# token is single-use; replaying a CONSUMED token revokes all refresh tokens
# for that key, so store the new one immediately and only once.
set -euo pipefail
API_BASE="${RADIUMONE_API_BASE:-https://api-sandbox.radiumone.io/gateway}"
curl -sS -X POST "$API_BASE/v1/auth/token/refresh" \
-H "Content-Type: application/json" \
-d @request.json#!/usr/bin/env python3
"""Rotate a refresh token for a new access + refresh pair. Python 3.10+, requests."""
import json
import os
from pathlib import Path
import requests
API_BASE = os.environ.get("RADIUMONE_API_BASE", "https://api-sandbox.radiumone.io/gateway")
def refresh_access_token() -> dict:
body = json.loads((Path(__file__).parent / "request.json").read_text())
if os.environ.get("RADIUMONE_REFRESH_TOKEN"):
body["refresh_token"] = os.environ["RADIUMONE_REFRESH_TOKEN"]
resp = requests.post(f"{API_BASE}/v1/auth/token/refresh", json=body, timeout=30)
payload = resp.json()
if not resp.ok:
raise RuntimeError(f"auth/token/refresh failed: {payload.get('type') or payload.get('code')} ({resp.status_code})")
# Store the NEW refresh_token immediately — the old one is single-use.
return payload
if __name__ == "__main__":
print(json.dumps(refresh_access_token(), indent=2))
{
"data": {
"access_token": "<string>",
"expires_in": 123,
"merchant_id": "<string>",
"publishable_key": "<string>",
"redirect_secret": "<string>",
"refresh_expires_in": 123,
"refresh_token": "<string>",
"token_type": "Bearer"
},
"message": "<string>",
"request_id": "<string>",
"status": "ok"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"request_id": "<string>",
"code": "<string>",
"retry_allowed": true,
"errors": [
{
"pointer": "<string>",
"parameter": "<string>",
"code": "<string>",
"detail": "<string>"
}
]
}{
"detail": "Missing or invalid Bearer token.",
"status": 401,
"title": "Authentication Required",
"type": "urn:radiumone:gateway:authentication-required"
}{
"detail": "An unexpected error occurred.",
"status": 500,
"title": "Internal Server Error",
"type": "urn:radiumone:gateway:internal-server-error"
}{
"detail": "A downstream dependency is unavailable or did not respond in time.",
"status": 503,
"title": "Service Unavailable",
"type": "urn:radiumone:gateway:service-unavailable"
}Rotate refresh token - Payments API
Exchange a refresh token for a new access token and refresh token pair. Each refresh token works once, so store the new one.
#!/usr/bin/env bash
# Rotate a refresh token for a new access + refresh pair. The old refresh
# token is single-use; replaying a CONSUMED token revokes all refresh tokens
# for that key, so store the new one immediately and only once.
set -euo pipefail
API_BASE="${RADIUMONE_API_BASE:-https://api-sandbox.radiumone.io/gateway}"
curl -sS -X POST "$API_BASE/v1/auth/token/refresh" \
-H "Content-Type: application/json" \
-d @request.json#!/usr/bin/env python3
"""Rotate a refresh token for a new access + refresh pair. Python 3.10+, requests."""
import json
import os
from pathlib import Path
import requests
API_BASE = os.environ.get("RADIUMONE_API_BASE", "https://api-sandbox.radiumone.io/gateway")
def refresh_access_token() -> dict:
body = json.loads((Path(__file__).parent / "request.json").read_text())
if os.environ.get("RADIUMONE_REFRESH_TOKEN"):
body["refresh_token"] = os.environ["RADIUMONE_REFRESH_TOKEN"]
resp = requests.post(f"{API_BASE}/v1/auth/token/refresh", json=body, timeout=30)
payload = resp.json()
if not resp.ok:
raise RuntimeError(f"auth/token/refresh failed: {payload.get('type') or payload.get('code')} ({resp.status_code})")
# Store the NEW refresh_token immediately — the old one is single-use.
return payload
if __name__ == "__main__":
print(json.dumps(refresh_access_token(), indent=2))
{
"data": {
"access_token": "<string>",
"expires_in": 123,
"merchant_id": "<string>",
"publishable_key": "<string>",
"redirect_secret": "<string>",
"refresh_expires_in": 123,
"refresh_token": "<string>",
"token_type": "Bearer"
},
"message": "<string>",
"request_id": "<string>",
"status": "ok"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"instance": "<string>",
"request_id": "<string>",
"code": "<string>",
"retry_allowed": true,
"errors": [
{
"pointer": "<string>",
"parameter": "<string>",
"code": "<string>",
"detail": "<string>"
}
]
}{
"detail": "Missing or invalid Bearer token.",
"status": 401,
"title": "Authentication Required",
"type": "urn:radiumone:gateway:authentication-required"
}{
"detail": "An unexpected error occurred.",
"status": 500,
"title": "Internal Server Error",
"type": "urn:radiumone:gateway:internal-server-error"
}{
"detail": "A downstream dependency is unavailable or did not respond in time.",
"status": 503,
"title": "Service Unavailable",
"type": "urn:radiumone:gateway:service-unavailable"
}Body
Request body for POST /auth/token/refresh.
Opaque refresh token previously issued by /auth/token or /auth/token/refresh.
53^r1rt_[0-9a-f]{48}$Response
Successful Response
Standard success envelope. Every successful response has this shape, with the operation's own payload under data.
The operation's result. Its shape is documented per operation; omitted on responses that carry no payload.
Show child attributes
Show child attributes
Optional human-readable note. Omitted from the response when not set, which is the case for every payment operation today. Never parse it.
Correlation ID for this HTTP request, for logs and support. Send your own in the X-Request-Id header (letters, digits and hyphens, up to 36 characters -- other characters are stripped) or the gateway generates one. This is NOT the request_id idempotency key you send in a transaction body; the two are unrelated.
Always ok on a successful (2xx) response. Errors use a different body shape entirely (RFC 9457 problem details), so branch on the HTTP status code, not on this field.