Reference

Hosted API

Every delivered project exposes one HTTP API on the platform. This page describes how to authenticate, discover your endpoints, call them, and read the result.

Base URL

All calls use this origin and the /api/v1 prefix.

Base URL
https://app.sreverse.simpalabs.com/api/v1

Authentication

Send your key as a bearer token on every call. There is no session cookie and no signed request to build yourself.

Authorization: Bearer srv_1a2b3c4d5e6f.<secret>

Keys are issued once, when the project is delivered, and shown a single time. The value above is a placeholder: replace srv_1a2b3c4d5e6f and <secret> with the key you were given. The account that owns the project can issue a replacement key, and revoke a key, from the project page.

The platform also accepts the key in an x-api-key header. Requests are authenticated by the header alone, so any origin may call the API and no ambient cookie credential is exposed.

Discovery

GET /api/v1 lists the endpoints your key can call, the connector version behind them, and recent usage. Start here rather than guessing at endpoint names.

The discovery call is the same URL as the base URL. It returns the endpoints available to that key, the connector version, and the ten most recent calls on the project.

curl -sS "https://app.sreverse.simpalabs.com/api/v1" \
  -H "Authorization: Bearer srv_1a2b3c4d5e6f.<secret>"

The response looks like this.

{
  "project": { "code": "SRV-2026-0001", "app": "Example app", "status": "delivered" },
  "connector": {
    "title": "Example app mobile API",
    "version": 2,
    "activatedAt": "2026-02-04T10:15:00.000Z",
    "signsRequests": true,
    "encryptsRequests": false
  },
  "key": { "label": "Default key", "callCount": 128 },
  "endpoints": [
    {
      "name": "lookup",
      "method": "POST",
      "path": "/v2/reference/lookup",
      "description": "Look up a reference and return its status.",
      "anonymous": false,
      "input": [
        {
          "name": "reference",
          "type": "string",
          "required": true,
          "description": "The reference to look up."
        }
      ]
    }
  ],
  "usage": [
    {
      "endpoint": "lookup",
      "status": 200,
      "upstreamStatus": 200,
      "latencyMs": 412,
      "at": "2026-02-04T10:31:07.000Z"
    }
  ],
  "call": "https://app.sreverse.simpalabs.com/api/v1/<endpoint>"
}

The call field shows the URL shape for executing an endpoint. The input array on each endpoint lists the fields that endpoint accepts, which is what you send in the request body. A key with no active connector returns no_active_endpoint.

Calling an endpoint

POST /api/v1/<endpoint> executes one recovered workflow and returns its result.

The JSON request body supplies the input fields that discovery declared for the endpoint. Query string parameters fill in anything the body omits. Send POST for every endpoint; GET also works and takes its input from the query string only, which is convenient for a check from a browser. The method the upstream expects is decided by the connector, not by how you call the platform.

POST /api/v1/lookup
Content-Type: application/json

{"reference": "ABC123"}
GET /api/v1/lookup?reference=ABC123

The platform runs the whole recovered flow on your behalf: the login, the request signing, any payload encryption, and the decryption of the response. You send plain JSON and receive the decoded body, or the single field the connector selects from it.

Examples

Three complete calls

Each sample calls an endpoint named lookup with a body of {"reference": "ABC123"}.

curl

curl -sS -X POST "https://app.sreverse.simpalabs.com/api/v1/lookup" \
  -H "Authorization: Bearer srv_1a2b3c4d5e6f.<secret>" \
  -H "Content-Type: application/json" \
  -d '{"reference": "ABC123"}'

Python with requests

import requests

BASE_URL = "https://app.sreverse.simpalabs.com/api/v1"
API_KEY = "srv_1a2b3c4d5e6f.<secret>"

response = requests.post(
    BASE_URL + "/lookup",
    headers={
        "Authorization": "Bearer " + API_KEY,
        "Content-Type": "application/json",
    },
    json={"reference": "ABC123"},
    timeout=30,
)

print("latency:", response.headers.get("x-sreverse-latency-ms"))

if response.ok:
    print(response.json())
else:
    failure = response.json()
    print(failure["error"]["code"], failure["error"]["message"])
    for line in failure.get("trace", []):
        print(line)

TypeScript with fetch

const BASE_URL = "https://app.sreverse.simpalabs.com/api/v1";
const API_KEY = "srv_1a2b3c4d5e6f.<secret>";

const response = await fetch(BASE_URL + "/lookup", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ reference: "ABC123" }),
});

const latencyMs = response.headers.get("x-sreverse-latency-ms");

if (!response.ok) {
  const failure = await response.json();
  throw new Error(failure.error.code + ": " + failure.error.message);
}

const result = await response.json();
console.log(result, latencyMs);

Reading the response

  • A successful call returns HTTP 200 and the decoded body as JSON. If the connector selects a single field from the upstream response, that value is returned on its own.
  • The metadata you usually want is in the response headers, not the body: the endpoint name, the latency, the upstream status and the connector id.
  • A failed call returns the status from the error table below and a body with an error object. Check error.code rather than the message, which is written for a person and may change.

Response headers

These are present on calls that reached the connector. A request rejected before that, such as one with an invalid key or malformed JSON, returns only the CORS headers.

HeaderMeaning
x-sreverse-endpointThe endpoint name the call ran against.
x-sreverse-latency-msTotal milliseconds the platform spent on the call, including the upstream round trip.
x-sreverse-upstream-statusThe HTTP status the upstream returned. Absent when the call never reached it.
x-sreverse-connectorThe id of the connector version that handled the call. Quote it when reporting a problem.

Errors

Failures return an error object and a trace array describing what the connector did.

{
  "error": {
    "code": "upstream_error",
    "message": "The upstream service returned 503.",
    "upstreamStatus": 503
  },
  "trace": [
    "session established with 2 captured value(s)",
    "POST https://api.example.com/v2/reference/lookup -> 503 in 388ms",
    "failed: The upstream service returned 503."
  ]
}

The trace is written to be safe to share. It lists the steps the connector took, redacted of secrets and credentials, and it is the first thing to include when reporting a problem.

CodeHTTP statusMeaning
missing_key401No Authorization bearer header or x-api-key was sent.
invalid_key401The key matches no issued key, or it has been revoked.
no_active_endpoint409The project has no active connector, for example before delivery or while a connector is disabled.
invalid_json400The request body was not valid JSON.
unknown_endpoint404The connector has no endpoint with that name.
upstream_error502The upstream returned an error status. Its status is in error.upstreamStatus and in the x-sreverse-upstream-status header.
upstream_timeout502The upstream did not answer within the connector timeout, which is 30 seconds by default.
login_failed502The connector login call returned an error status.
session_extract_failed502Login succeeded but a session value mapped from the response was absent.
decrypt_failed502An encrypted upstream response could not be decrypted with the configured key.
template_missing_value502A request template referenced an input field or secret that was not supplied.
invalid_key_length502The configured signing or encryption key did not decode to the length the algorithm requires.

Guarantees

  • Upstream credentials stay server side. The credentials recovered during the work, including signing keys and account passwords, are held by the platform and used only to make your calls. They are never sent to your application or your browser.
  • Your key only ever reaches the platform. It authenticates you to the hosted endpoint. Everything the upstream expects, including signatures and encrypted payloads, is built on the platform.
  • Every call is metered. Each call is recorded with its endpoint, status, upstream status and latency. The discovery response reports the call count for the key and the ten most recent calls on the project.
  • Keys can be revoked at any time. Revoke a key from the project page and it stops working immediately, after which it returns invalid_key with HTTP 401.