Build payments into your product with TPE virtual. Start integrating →
Logo

Responses

The response envelope, pagination, data types, HTTP status codes, and the error format used across the external API.

Every endpoint in the external API shapes responses, pages lists, and reports errors the same way. Read this page once, and it applies everywhere.

Success envelope

A single resource arrives wrapped in a data object:

{
  "data": {
    "id": "5a6b7c8d-9e0f-1a2b-3c4d-5e6f7a8b9c0d",
    "title": "Order #10428",
    "status": "active"
  }
}

Endpoints that perform an action rather than return a resource put a human-readable string in meta.message:

{
  "meta": {
    "message": "Payment link archived."
  }
}

Pagination

List endpoints return a data array alongside links and meta. To page through results, use the page and per_page query parameters. per_page defaults to 15.

{
  "data": [
    { "id": "5a6b7c8d-9e0f-1a2b-3c4d-5e6f7a8b9c0d", "title": "Order #10428" },
    { "id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e", "title": "Order #10429" }
  ],
  "links": {
    "first": "https://api.mytpe.app/api/ext/links?page=1",
    "last": "https://api.mytpe.app/api/ext/links?page=4",
    "prev": null,
    "next": "https://api.mytpe.app/api/ext/links?page=2"
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "to": 15,
    "per_page": 15,
    "last_page": 4,
    "total": 58
  }
}

Most list endpoints also accept search, sort_by, and sort_dir, where sort_dir is asc or desc. Results are sorted by created_at desc unless you specify otherwise. Each resource page lists the sort_by values that endpoint accepts.

Data types

TypeRepresentation
IdentifiersUUID strings, such as "5a6b7c8d-9e0f-1a2b-3c4d-5e6f7a8b9c0d".
MoneyDecimal strings, such as "4500.00". The currency is a three-letter code, DZD.
Wallet amountsIntegers in centimes. 50000 means 500.00 DZD. See Wallet.
TimestampsISO 8601 in UTC, such as "2026-06-09T12:34:56.000000Z".
EnumsLowercase snake_case strings. See Statuses and enums.
Booleanstrue or false.

Money is a decimal string on most resources but an integer count of centimes on wallet endpoints. Mixing the two sends a payment 100 times too large or too small.

HTTP status codes

CodeMeaning
200 OKThe request succeeded.
201 CreatedThe API created the resource.
204 No ContentThe request succeeded and returned no body.
401 UnauthorizedThe API credentials are missing or invalid.
403 ForbiddenThe credentials are valid, but the account can't perform this action.
404 Not FoundThe resource doesn't exist, or it belongs to another account.
422 Unprocessable EntityValidation failed, or a business rule rejected the request.
500 Internal Server ErrorThe request failed unexpectedly.
503 Service UnavailableA dependency, such as the payment gateway, is temporarily unavailable.

Errors

Errors follow JSON:API. The top-level errors key holds an array, even when only one error is present:

404 Not Found
{
  "errors": [
    {
      "status": "404",
      "code": "NOT_FOUND",
      "title": "Resource not found",
      "detail": null,
      "meta": []
    }
  ]
}

Each member of the array contains these fields:

FieldTypeDescription
statusstringThe HTTP status code, as a string.
codestringA stable, machine-readable identifier. Branch on this value.
titlestringA human-readable summary. This text can change; don't match on it.
detailstring | nullExtra context, when the API has any to add.
metaobject | arrayField-level validation messages, or an empty array.

errors is an array, not an object, and a failed request has no top-level message key. Reading response.error or response.message yields undefined for every error the API returns.

Common error codes

HTTPcodeWhen it occurs
401MISSING_API_CREDENTIALSOne or both credential headers are absent.
401INVALID_API_CREDENTIALSBoth headers are present, but the key or secret doesn't match.
403NON_TRADER_API_USEThe credentials belong to an account that isn't a trader.
403PLAN_EXTERNAL_API_REQUIREDThe trader's plan doesn't include external API access.
403WORKSPACE_ACCESS_DENIEDThe X-Workspace-Id value names a workspace the account can't reach.
404NOT_FOUNDThe resource doesn't exist, or it belongs to another account.
422VALIDATION_ERROROne or more fields failed validation.
422PLAN_LIMIT_REACHEDCreating this resource would exceed the plan's limit.
503SERVICE_UNAVAILABLEA dependency is temporarily unavailable.

Validation errors

A validation failure returns 422 with the code VALIDATION_ERROR. Field-level messages live in meta, keyed by field name, with an array of messages for each field:

422 Unprocessable Entity
{
  "errors": [
    {
      "status": "422",
      "code": "VALIDATION_ERROR",
      "title": "Validation failed",
      "detail": null,
      "meta": {
        "amount": ["The amount field is required when amount mode is fixed."],
        "payment_instance_id": ["The selected payment instance id is invalid."]
      }
    }
  ]
}

Nested fields use dot notation in the key, such as "udf1.value".

Handle errors

Branch on the HTTP status first, then on errors[0].code. Never match on title, because that text is localized and subject to change.

const res = await fetch(url, { headers });

if (!res.ok) {
  const { errors } = await res.json();
  const [error] = errors;

  switch (error.code) {
    case "INVALID_API_CREDENTIALS":
      throw new Error("Check MYTPE_API_KEY and MYTPE_API_SECRET.");
    case "VALIDATION_ERROR":
      // error.meta maps each field to its messages.
      throw new Error(Object.entries(error.meta).map(([f, m]) => `${f}: ${m[0]}`).join("; "));
    default:
      throw new Error(`${error.code}: ${error.title}`);
  }
}

On this page