Skip to main content

Overview

The HTTP API provides three endpoints for terminal and payment management:
MethodEndpointDescription
GET/v1/terminalsList available terminals
POST/v1/terminals/{terminalId}/paymentsInitiate a payment
GET/v1/transactions/{transactionId}Check transaction status

Base URL

https://{your-api-endpoint}/v1
Replace {your-api-endpoint} with your provisioned API endpoint. Contact support@moduluslabs.io to obtain your endpoint URL.

GET /v1/terminals

Retrieve all active terminals in your group.

Headers

HeaderRequiredDescription
x-api-keyYesYour API key
x-timestampYesISO 8601 timestamp
x-signatureYesHMAC-SHA256 signature

Response (200 OK)

{
  "terminals": [
    {
      "connectionId": "abc123xyz",
      "terminalId": "TERM-001",
      "deviceId": "TERM-001",
      "connectedAt": "2024-01-15T10:30:00.000Z",
      "lastActivity": "2024-01-15T10:35:00.000Z",
      "status": "online",
      "metadata": {}
    }
  ],
  "count": 1,
  "timestamp": "2024-01-15T10:35:30.000Z"
}

Response Fields

FieldTypeDescription
terminalsarrayList of available terminals
terminals[].connectionIdstringUnique connection identifier
terminals[].terminalIdstringPrimary identifier (deviceId if available)
terminals[].deviceIdstringStable device identifier (if configured)
terminals[].connectedAtstringISO 8601 timestamp of connection
terminals[].lastActivitystringISO 8601 timestamp of last activity
terminals[].statusstringonline, offline, or reconnecting
terminals[].metadataobjectCustom terminal metadata
countnumberTotal number of terminals
timestampstringISO 8601 timestamp of the response

Error Responses

StatusCodeDescription
401UNAUTHORIZEDInvalid or missing authentication
403GROUP_MISMATCHOnly desktop devices can list terminals
500INTERNAL_ERRORServer error

Code Example

curl -X GET "https://{your-api-endpoint}/v1/terminals" \
  -H "x-api-key: your-api-key" \
  -H "x-timestamp: 2024-01-15T10:30:00.000Z" \
  -H "x-signature: <computed-signature>"

POST /v1/terminals//payments

Initiate a payment to a specific terminal. By default, this endpoint uses long-polling and waits up to 90 seconds for the terminal to respond. Alternatively, set webhookMode: true for immediate response with asynchronous notification via webhook.

Path Parameters

terminalId
string
required
The terminal identifier. Resolved as deviceId first, falling back to connectionId. See Terminal ID Resolution.
The terminalId is resolved as a deviceId first, falling back to connectionId for legacy integrations. See Terminal ID Resolution for details.

Headers

HeaderRequiredDescription
Content-TypeYesapplication/json
x-api-keyYesYour API key
x-timestampYesISO 8601 timestamp
x-signatureYesHMAC-SHA256 signature

Request Body

transactionId
string
Unique transaction identifier. Auto-generated if not provided.
amount
string | number
required
Payment amount.
currency
string
required
ISO 4217 currency code (e.g., "USD", "EUR").
paymentMethod
string
required
Payment method: "CARD", "CASH", "MOBILE", or "OTHER".
products
array
Array of products in the transaction.
customerInfo
object
Customer information.
metadata
object
Custom key-value pairs for your use.
webhookMode
boolean
default:"false"
When true, disables 90-second long-polling and returns 202 Accepted immediately. The payment result will be delivered via webhook to your configured endpoints. Requires at least one webhook endpoint to be configured.

Request Example

{
  "transactionId": "TXN-20240115-001",
  "amount": "99.99",
  "currency": "USD",
  "paymentMethod": "CARD",
  "products": [
    {
      "id": "PROD-001",
      "name": "Widget",
      "price": "99.99",
      "quantity": 1
    }
  ],
  "customerInfo": {
    "customerId": "CUST-123",
    "email": "customer@example.com"
  },
  "metadata": {
    "orderId": "ORD-12345"
  }
}

Response (200 OK) - Success

{
  "transactionId": "TXN-20240115-001",
  "status": "SUCCESS",
  "paymentResponse": {
    "transactionId": "TXN-20240115-001",
    "status": "SUCCESS",
    "amount": "99.99",
    "currency": "USD",
    "paymentMethod": "CARD",
    "authorizationCode": "AUTH123456",
    "receiptData": "...",
    "timestamp": "2024-01-15T10:37:30.000Z"
  },
  "timestamp": "2024-01-15T10:37:30.000Z"
}

Response (202 Accepted) - Webhook Mode

Returned when webhookMode: true. The payment has been sent to the terminal and results will be delivered via webhook:
{
  "transactionId": "TXN-20240115-001",
  "status": "ACCEPTED",
  "message": "Payment sent to terminal. Result will be delivered via webhook.",
  "timestamp": "2024-01-15T10:36:00.000Z"
}
When using webhook mode, you must have at least one webhook endpoint configured. The payment result will be delivered to your endpoints as a payment.completed, payment.failed, payment.cancelled, or payment.timeout event.

Response (202 Accepted) - Terminal Disconnected

Returned when the terminal disconnects during payment processing (standard mode only):
{
  "transactionId": "TXN-20240115-001",
  "status": "PENDING",
  "error": {
    "code": "TERMINAL_CONNECTION_ERROR",
    "message": "Terminal disconnected during payment processing"
  },
  "timestamp": "2024-01-15T10:37:30.000Z"
}

Response (504 Gateway Timeout)

Returned when the terminal doesn’t respond within 90 seconds:
{
  "error": {
    "code": "TIMEOUT",
    "message": "Terminal did not respond within 90 seconds",
    "details": {
      "note": "Transaction may still be processed. Check status via GET /v1/transactions/{id}"
    }
  },
  "transactionId": "TXN-20240115-001",
  "timestamp": "2024-01-15T10:39:00.000Z"
}
After a timeout, always check the transaction status using GET /v1/transactions/{transactionId}. The payment may have completed on the terminal after the HTTP timeout.

Error Responses

StatusCodeDescription
400INVALID_REQUESTInvalid request body or missing fields
400INVALID_AMOUNTAmount doesn’t match products total
400NO_WEBHOOK_ENDPOINTSwebhookMode: true requires at least one webhook endpoint
401UNAUTHORIZEDInvalid authentication
403GROUP_MISMATCHTerminal not in your group
404TERMINAL_NOT_FOUNDTerminal not found
409PAYMENT_IN_PROGRESSAnother payment is being processed
502TERMINAL_CONNECTION_ERRORFailed to communicate with terminal
503TERMINAL_OFFLINETerminal is offline
504TIMEOUTTerminal did not respond in time

Code Example

curl -X POST "https://{your-api-endpoint}/v1/terminals/TERM-001/payments" \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -H "x-timestamp: 2024-01-15T10:36:00.000Z" \
  -H "x-signature: <computed-signature>" \
  -d '{
    "transactionId": "TXN-20240115-001",
    "amount": "99.99",
    "currency": "USD",
    "paymentMethod": "CARD",
    "products": [
      {
        "id": "PROD-001",
        "name": "Widget",
        "price": "99.99",
        "quantity": 1
      }
    ],
    "metadata": {
      "orderId": "ORD-12345"
    }
  }'

GET /v1/transactions/

Retrieve the status of a transaction. Useful for reconciliation or checking status after a timeout.

Path Parameters

transactionId
string
required
The transaction ID to query.

Headers

HeaderRequiredDescription
x-api-keyYesYour API key
x-timestampYesISO 8601 timestamp
x-signatureYesHMAC-SHA256 signature

Response (200 OK)

{
  "transactionId": "TXN-20240115-001",
  "status": "COMPLETED",
  "request": {
    "transactionId": "TXN-20240115-001",
    "amount": "99.99",
    "currency": "USD",
    "paymentMethod": "CARD"
  },
  "response": {
    "transactionId": "TXN-20240115-001",
    "status": "SUCCESS",
    "amount": "99.99",
    "currency": "USD",
    "paymentMethod": "CARD",
    "authorizationCode": "AUTH123456",
    "timestamp": "2024-01-15T10:37:30.000Z"
  },
  "createdAt": "2024-01-15T10:37:00.000Z",
  "updatedAt": "2024-01-15T10:37:30.000Z",
  "completedAt": "2024-01-15T10:37:30.000Z",
  "timestamp": "2024-01-15T10:40:00.000Z"
}

Response Fields

FieldTypeDescription
transactionIdstringUnique transaction identifier
statusstringTransaction status (see below)
requestobjectOriginal payment request
responseobjectPayment response (if completed)
createdAtstringISO 8601 timestamp of creation
updatedAtstringISO 8601 timestamp of last update
completedAtstringISO 8601 timestamp of completion
terminalDeviceIdstringTerminal device ID (if available)
voidedAtstringTimestamp when voided (if applicable)
voidReasonstringReason for voiding (if voided)
timestampstringISO 8601 timestamp of this response

Transaction Status Values

StatusDescription
PENDINGTransaction created, awaiting terminal response
COMPLETEDTransaction completed successfully
FAILEDTransaction failed (see error details)
CANCELLEDTransaction was cancelled
AWAITING_RECONNECTTerminal disconnected, waiting for reconnection
VOIDEDPayment was voided (terminal reconnected too late)

Error Responses

StatusCodeDescription
401UNAUTHORIZEDInvalid authentication
403GROUP_MISMATCHTransaction not in your group
404TRANSACTION_NOT_FOUNDTransaction not found
500INTERNAL_ERRORServer error

Code Example

curl -X GET "https://{your-api-endpoint}/v1/transactions/TXN-20240115-001" \
  -H "x-api-key: your-api-key" \
  -H "x-timestamp: 2024-01-15T10:40:00.000Z" \
  -H "x-signature: <computed-signature>"

Rate Limiting

The API implements rate limiting to ensure service stability. Current limits are applied per API key.
Limit TypeValue
Requests per minuteContact support
Concurrent payments1 per terminal
If you exceed rate limits, you will receive a 429 Too Many Requests response:
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Please slow down."
  },
  "timestamp": "2024-01-15T10:40:00.000Z"
}
Contact support@moduluslabs.io if you require higher rate limits for your integration.

Troubleshooting

Common causes:
  • Invalid API key or secret
  • System clock not synchronized (timestamp must be within 5 minutes)
  • Incorrect SHA256 body hash computation (must be hex-encoded)
  • String-to-sign format mismatch (check newline characters)
Debug steps:
  1. Verify your API key and secret are correct
  2. Check your system clock is synchronized with NTP
  3. Log the string-to-sign and compare with documentation
  4. Ensure body hash is computed on the exact JSON string sent
What to do after a 504 timeout:
  1. Do not retry the payment immediately
  2. Call GET /v1/transactions/{transactionId} to check actual status
  3. The payment may have completed on the terminal
  4. Only retry if status is FAILED or CANCELLED
Prevention:
  • Verify terminal is online before initiating payments
  • Monitor terminal status with GET /v1/terminals
Causes:
  • Terminal is offline
  • Using wrong terminal ID (connectionId vs deviceId)
  • Terminal in different group
Solutions:
  1. Refresh terminal list with GET /v1/terminals
  2. Use deviceId instead of connectionId
  3. Verify API key matches terminal’s group
Cause: Another payment is already being processed on the terminal.Solution: Wait for the current payment to complete before initiating a new one. Terminals can only process one payment at a time.

Next Steps