Skip to main content
Rinne uses standard HTTP status codes and provides detailed error responses to help you debug issues quickly.

Error response format

All errors follow a consistent structure:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation error",
    "status": 400,
    "path": "/v1/transactions",
    "timestamp": "2025-01-21T10:30:00.000Z",
    "requestId": "req_123456789",
    "details": {
      "issues": [
        {
          "field": "amount",
          "type": "REQUIRED",
          "message": "Field 'amount' is required"
        }
      ]
    }
  }
}

Error fields

  • code: Machine-readable error code
  • message: Human-readable error message
  • status: HTTP status code
  • path: API endpoint that generated the error
  • timestamp: When the error occurred
  • requestId: Unique request identifier for support
  • details: Additional error-specific information

HTTP status codes

CodeDescriptionCommon causes
400Bad RequestInvalid input, validation errors
401UnauthorizedMissing or invalid API key
403ForbiddenInsufficient permissions
404Not FoundResource doesn’t exist
409ConflictDuplicate resource, invalid state
500Internal Server ErrorServer-side error
502Bad GatewayProvider integration error

Common error codes

VALIDATION_ERROR (400)

Input validation failed. Check the details.issues array for specific field errors.
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation error",
    "details": {
      "issues": [
        {
          "field": "amount",
          "type": "INVALID_TYPE",
          "message": "Expected number, received string",
          "value": "invalid"
        }
      ]
    }
  }
}
Solution: Fix the invalid fields and retry the request.
Card credential fields (card_data.number, card_data.cvv, card_data.network_token, card_data.cryptogram, and the 3DS card.number) are accepted only as encrypted values from rinne-js. A plaintext value triggers a per-field VALIDATION_ERROR issue telling you to send the encrypted value from rinne-js instead. The rejected value is never echoed back in the error response.

AUTHENTICATION_ERROR (401)

API key is missing or invalid.
{
  "error": {
    "code": "AUTHENTICATION_ERROR",
    "message": "Invalid or missing API key",
    "details": {
      "reason": "API key not found"
    }
  }
}
Solution: Verify your API key is correct and included in the x-api-key header.

AUTHORIZATION_ERROR (403)

You don’t have permission to access the resource.
{
  "error": {
    "code": "AUTHORIZATION_ERROR",
    "message": "You need 'transaction.create' permission to access this resource"
  }
}
Solution: Check your user roles and permissions, or use an API key with appropriate access.

RESOURCE_NOT_FOUND (404)

The requested resource doesn’t exist.
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "Transaction with ID 'tx_123' not found"
  }
}
Solution: Verify the resource ID is correct and belongs to your company.

CONFLICT_ERROR (409)

Resource already exists or operation conflicts with current state.
{
  "error": {
    "code": "CONFLICT_ERROR",
    "message": "Company with this document_number already exists",
    "details": {
      "field": "document_number",
      "value": "16525269000121"
    }
  }
}
Solution: Check for existing resources or verify the resource state allows the operation.

INTEGRATION_ERROR (502)

Provider integration failed.
{
  "error": {
    "code": "INTEGRATION_ERROR",
    "message": "Integration error with provider CELCOIN",
    "status": 502
  }
}
Solution: Retry the request. If the error persists, contact support with the requestId.

Handling validation errors

Validation errors include detailed information about each invalid field:
try {
  const response = await createTransaction(data);
} catch (error) {
  if (error.status === 400 && error.code === 'VALIDATION_ERROR') {
    error.details.issues.forEach(issue => {
      console.log(`Field ${issue.field}: ${issue.message}`);
      // Display error to user
    });
  }
}

Idempotency

Use the request_id field to safely retry requests:
# First attempt - network error
POST /v1/transactions
{ "request_id": "order-123", ... }
# Network timeout

# Retry with same request_id
POST /v1/transactions
{ "request_id": "order-123", ... }
# Returns existing transaction if first request succeeded
This prevents duplicate transactions when retrying failed requests.

Rate limiting

Rinne applies request rate limits to keep the platform stable: 1000 req/s for transaction creation and 3DS session creation and authentication POST requests and 50 req/s for all other requests. Each limit is a shared pool across all matching endpoints, not a per-endpoint allowance. Requests within the limit always succeed; only the excess requests above the limit are rejected, with no account block or penalty. See the Rate limits guide for full details. Rejected requests return a 429 Too Many Requests status code with no response body. The limit details are returned in the response headers instead:
HTTP/1.1 429 Too Many Requests
x-ratelimited: true
x-ratelimit-limit: 50, 50;w=1
x-ratelimit-remaining: 0
x-ratelimit-reset: 1
Detect a rate limit rejection from the 429 status code and the x-ratelimit-* headers, not from a response body. Implement exponential backoff when retrying:
async function retryWithBackoff(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status === 429 && i < maxRetries - 1) {
        const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      throw error;
    }
  }
}

Logging and debugging

Request IDs

Every response includes a requestId that you can use when contacting support:
{
  "error": {
    "requestId": "req_123456789"
  }
}
Save request IDs for failed requests to help support diagnose issues.

Error monitoring

Implement error monitoring to track API errors:
app.use((error, req, res, next) => {
  // Log to monitoring service
  logger.error('Rinne API error', {
    code: error.code,
    status: error.status,
    requestId: error.requestId,
    path: req.path
  });
  
  // Send to error tracking (Sentry, etc.)
  Sentry.captureException(error);
});

Next steps

Webhooks

Handle webhook delivery failures

API Reference

View all error response schemas