API Reference
Explore the TSPay API using the interactive Swagger documentation or browse the reference below.
Table of contents
- Interactive API Documentation
- API Endpoint Categories
- HTTP Request Structure
- Naming Conventions
- HTTP Response Structure
- Common HTTP Status Codes
- Data Types and Formats
- Rate Limiting
- Idempotency
- Funding Requirements
- OpenAPI Specification
- Versioning Policy
- Next Steps
Interactive API Documentation
Access the interactive Swagger UI to explore endpoints, test requests, and view detailed request/response schemas.
Swagger UI
Interactive API Explorer:
Access the full Swagger UI at your deployed API instance:
- Production:
https://tspay-api.live.travelsoftpay.com/swagger-ui/index.html - Sandbox:
https://tspay-api.sandbox.travelsoftpay.com/swagger-ui/index.html
OpenAPI Specification (JSON):
- Production:
https://tspay-api.live.travelsoftpay.com/v3/api-docs - Sandbox:
https://tspay-api.sandbox.travelsoftpay.com/v3/api-docs
Access to the TSPay API, Swagger UI, and OpenAPI specification endpoints is restricted by IP allowlisting on both Sandbox and Production environments. Contact TSPay support to register your IP addresses before starting integration.
The Swagger UI includes built-in authentication. Click Authorize and provide a valid access token (JWT) to test authenticated endpoints directly from the browser. Use the
accessToken, not therefreshToken, when authorizing requests in Swagger UI.
API Endpoint Categories
Available in v1.0
| Endpoint | Method | Auth required | Description |
|---|---|---|---|
/api/v1/auth/login | POST | No | Authenticate and receive JWT tokens |
/api/v1/auth/refresh | POST | Yes | Obtain a new access token using the refresh token |
/api/v1/auth/logout | POST | Yes | Invalidate the current refresh token and terminate the session |
/api/v1/issuing/cards | POST | Yes | Create a new virtual card |
/api/v1/auth/refreshrequires a currently valid (non-expired) access token in theAuthorizationheader. The token is used to identify and authenticate the credential requesting the refresh. Proactively refresh the access token before it expires — if the access token has already expired, callPOST /api/v1/auth/loginto obtain a new session.
View Authentication Guide → · View Virtual Cards Guide →
Planned for a future version
| Endpoint | Method | Description |
|---|---|---|
/api/v1/issuing/cards/{cardId} | GET | Retrieve card details |
/api/v1/issuing/cards | GET | List cards |
/api/v1/issuing/cards/{cardId} | PATCH | Update card properties or cancel |
The endpoints listed under “Planned for a future version” are not available in v1.0 and should not be called.
v1.0 Scope: The v1.0 API covers card creation only. Authorization event notifications, settlement confirmations, and transaction history are not available in v1.0. These capabilities are planned for a future version. Partners requiring real-time transaction visibility should contact TSPay support to discuss available options.
HTTP Request Structure
Base URLs
Sandbox and Production are fully isolated environments with separate credentials and data:
| Environment | Base URL |
|---|---|
| Production | https://tspay-api.live.travelsoftpay.com |
| Sandbox | https://tspay-api.sandbox.travelsoftpay.com |
Tokens issued in one environment cannot be used in the other. Use Sandbox for development and testing.
Request Headers
All requests must be sent over HTTPS. Requests sent over HTTP are rejected. HTTPS is required for all endpoints.
All requests must include Content-Type: application/json. All endpoints except /api/v1/auth/login additionally require the Authorization header:
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
The Bearer prefix (including the trailing space) is required.
Request Body
Request bodies must be valid JSON:
{
"field1": "value1",
"field2": 123,
"nested": {
"field3": true
}
}
Naming Conventions
JSON field names use camelCase and are case-sensitive. Enum values are documented per field and are case-sensitive.
Examples:
status:activecardType:MTA- Query parameter:
revealDetails=true
HTTP Response Structure
Success Response
Status Code: 200 OK or 201 Created
{
"cardId": "ic_1234567890abcdef",
"status": "active",
"currency": "EUR"
}
Error Response
Status Code: 4xx or 5xx
{
"correlationId": "2aaa9f82-4873-4ba9-a0a3-e2228ff25078",
"status": 400,
"message": "Invalid request parameters",
"details": {},
"timestamp": "2025-01-10T14:30:00Z"
}
| Field | Description |
|---|---|
correlationId | Unique identifier for this request — provide to TSPay support when reporting issues |
status | HTTP status code (not a business-level status field) |
message | Human-readable description of the error |
details | Optional structured object providing field-level validation errors or additional diagnostic data. The structure of this object varies by error type — use the HTTP status code for programmatic error handling, not the contents of details |
timestamp | When the error occurred (ISO-8601 UTC) |
Clients should rely on the HTTP status code for programmatic error handling. The
messagefield is intended for diagnostics and may change over time. Thedetailsobject structure is not guaranteed to be stable across error types — do not parse it for control flow.
Common HTTP Status Codes
| Code | Status | Meaning |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request format or parameters |
| 401 | Unauthorized | Authentication failure — missing, invalid, or expired token |
| 403 | Forbidden | Authenticated but not authorized for this operation |
| 404 | Not Found | Resource does not exist |
| 409 | Conflict | Idempotency key reused outside the 24-hour idempotency window |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side error occurred |
| 503 | Service Unavailable | TSPay is temporarily unavailable. Retry after the interval specified in the Retry-After response header. |
Data Types and Formats
Currency Amounts
All monetary amounts are represented as integers in the smallest currency unit (minor units), following the ISO 4217 currency exponent. Examples below illustrate ISO 4217 currency exponents. Supported card currencies depend on the issuing account configuration.
| Currency | Exponent | Example |
|---|---|---|
| EUR, GBP | 2 decimals | 10000 = 100.00 |
{
"cardLimit": 50000,
"currency": "EUR"
}
This represents 500.00 EUR. Always use the correct exponent for the currency — passing 500 for EUR instead of 50000 will create a card with a 5.00 EUR limit.
Timestamps
All timestamps use ISO-8601 UTC format with the Z suffix:
{
"createdAt": "2025-01-10T14:30:00Z",
"config": {
"authorizationWindow": {
"startDate": "2025-01-10T00:00:00Z",
"endDate": "2025-01-17T23:59:59Z"
}
}
}
Token expiration fields (accessTokenExpiresAt, refreshTokenExpiresAt) are Unix timestamps (seconds since epoch).
Always use UTC timezone (
Zsuffix) for date fields. Regional date formats (DD/MM/YYYY) are not supported.
Currency Codes
ISO 4217 three-letter currency codes. The API accepts uppercase codes and returns them in uppercase:
{
"currency": "EUR"
}
Examples of supported values include EUR and GBP, depending on the issuing programme configuration of the issuing account.
Card Numbers (PAN)
By default, card data fields are masked in API responses:
pan: masked PAN (for example,************0054)cvc: masked value (***)
When revealDetails=true is used and the credential has the required permission, plaintext PAN and CVC are returned in the create-card response only.
Access to plaintext card data is restricted, requires specific permissions granted to the API credential, and is always audit-logged. See Card Data Security for PCI scope requirements.
Rate Limiting
Rate limits are applied per API credential. Rate limits are enforced using a sliding window and may change depending on platform load:
| Endpoint Type | Rate Limit |
|---|---|
| Authentication | 5 requests/minute |
| Card Operations | 120 requests/minute |
When rate limited, you will receive:
Status: 429 Too Many Requests
Response Header:
Retry-After: 60
Response Body:
{
"correlationId": "...",
"status": 429,
"message": "Rate limit exceeded",
"retryAfter": 60
}
Wait for the number of seconds indicated in Retry-After (or retryAfter in the body) before retrying the request.
Idempotency
Card creation is idempotent to prevent duplicate issuance during retries.
Idempotency Guarantees
- Idempotency window: 24 hours from the time the initial request is received by the TSPay API.
- Within the window: Repeated requests using the same
requestIdreturn the originally created card (200 OK) without creating a new card. This applies even if the new request payload differs — the original result is returned and the new payload is ignored. - After the window expires: Reusing a
requestIdafter the 24-hour idempotency window has expired returns409 Conflict. To create a new card, generate a new uniquerequestId. - Retry safety: It is safe to retry a failed request with the same
requestIdwithin the 24-hour window. If the original request succeeded internally but the response was not received (e.g., network timeout), the retry will return the originally created card. - Scope: Idempotency keys are scoped per issuing account. The same
requestIdvalue used by different issuing accounts does not collide. - Format:
requestIdmust be a valid UUID (e.g.,1230537f-e892-4678-b945-17bfb6d1a456).
Usage
The requestId must be unique per card creation request and included in the request body:
{
"requestId": "1230537f-e892-4678-b945-17bfb6d1a456",
"cardLimit": 10000,
"currency": "EUR"
}
Distinguishing New Creation from Idempotent Replay
The HTTP status code indicates whether a card was newly created or retrieved from the idempotency cache:
| Status Code | Meaning |
|---|---|
201 Created | A new card was created and provisioned |
200 OK | The request matched an existing requestId within the 24-hour window — the original card is returned; no new card was created |
Integrations that maintain internal ledgers or emit creation events must check the HTTP status code to distinguish these two cases. Treating a 200 response as a new card creation will result in duplicate entries in downstream systems.
Best Practices
Generate unique idempotency keys for each logical card creation:
// Recommended: Use UUID v4
// crypto.randomUUID() requires Node.js >= 14.17
const requestId = crypto.randomUUID();
// e.g., "1230537f-e892-4678-b945-17bfb6d1a456"
Funding Requirements
TSPay operates a prefunded issuing model.
Card creation does not reserve funds and does not require an available balance check at creation time. Cards may therefore be created even when no prefunded balance is currently available.
Available balance is checked when a merchant authorization is attempted. At that point, funds are ring-fenced for the authorization amount if sufficient balance is available. If not, the authorization is declined.
Contact TSPay support to understand your account’s funding requirements and replenishment process.
OpenAPI Specification
Download the complete OpenAPI 3.0 specification:
Sandbox:
JSON: https://tspay-api.sandbox.travelsoftpay.com/v3/api-docs
YAML: https://tspay-api.sandbox.travelsoftpay.com/v3/api-docs.yaml
Production:
JSON: https://tspay-api.live.travelsoftpay.com/v3/api-docs
YAML: https://tspay-api.live.travelsoftpay.com/v3/api-docs.yaml
You can import these specifications into tools like:
- Postman
- Insomnia
- Swagger Editor
- API testing frameworks
Versioning Policy
TSPay uses URI versioning under /api/v1. Backward-compatible additions may be introduced within v1. Breaking changes will be released under a new major versioned path.
Next Steps
- Virtual Cards - Learn about card creation
- Authentication - Understand JWT authentication
- Getting Started - Complete integration guide