Base URL, headers, the response envelope, value formats, id namespaces and how unknown fields are handled — every one of these applies to every route below unless a page says otherwise.

Base URL and transport

  • Base URL: https://proxy-api.infinimesh.net/v1, the public test hub (test networks only), used throughout this reference; your production address comes with your integration access. JSON in, JSON out (except GET /openapi.yaml, which returns YAML).
  • The gateway. The API is served by the hub’s gateway, in front of the hub. It checks the credential, sets the headers the hub needs, and passes the hub’s answers back unchanged. Its own refusals come in the same envelope, with an EPX code (The response envelope).
  • Who calls it. Your servers, with a secret API key. Your web pages, either through your backend (a proxy server that holds the key: Partner backend) or straight to the gateway with your public project id, from the origins your project lists. A secret key never goes in a page: the gateway does not take one from a browser (Authentication).

Request headers

  • One credential per call. A request carrying both x-api-key and x-project-id is refused, EPX0007 (400). The two credentials and what each may call: Authentication.
  • Nothing else is needed. The gateway builds every hub request itself: RequestId, User-Agent, Accept-Language: en (the hub’s messages are therefore always in English), your organization (from the credential) and its own credential for the hub. Nothing else you send reaches the hub but the path, the body, X-Infinity-Subject, and the query string of GET /orders and GET /onchain/{orderId}/refund (a query string on any other route is dropped).
  • From a web page, set only x-project-id, Content-Type and X-Infinity-Subject. The gateway’s CORS pre-flight allows exactly those three, and a browser refuses a call that sets any other non-standard header, x-api-key included (standard ones such as Accept need no pre-flight). A page’s subject names its visitor and proves nothing: anyone can send your public project id with any subject. A page can read an answer’s X-Request-Id, RateLimit-* and Retry-After headers.
  • Every POST carries a JSON object. Never send an empty body: sent as exactly application/json it is refused EMC0005, and otherwise the route answers EIN0001 reference body. A GET carries no body. The gateway refuses a body over 64 KiB, EPX0005 (413).

The request id

Every answer names the call twice: in the X-Request-Id response header and in the body’s request_id. The gateway makes a fresh id for every call it sends to the hub, so you never send one. Keep it with your logs, and quote it when you contact the hub team.

Rate-limit headers

Every call whose credential the gateway accepts reports the budget left in three headers, an EPX0080 or EPX0082 refusal included: For a secret key the bucket is your organization’s pool; for a project id, whichever of the project’s pool and the visitor’s own bucket is tighter. A refusal adds Retry-After, in seconds (API keys and rate limits).

The response envelope

Every response except GET /openapi.yaml is this envelope. A success carries data and no message or errors keys:
On failure success is false, data is absent, and errors holds the entries (a hub error has exactly one; framework validation can report several):
message is present here because EIN0008 is terminal; the hub’s availability and busy errors (EIN0050–EIN0099) carry no message. success is always present. request_id, message, data and errors are omitted when empty, and so are an error entry’s error_reference and error_params. The body’s request_id is missing on the hub’s per-IP limiter refusal (“DDoS check failed”); the X-Request-Id header still names the call. HTTP status. The hub answers 200 for success and 400 for every failure of its own — availability and busy codes included — and the gateway passes those answers through unchanged. The gateway answers its own refusals in the same envelope with a real status: 400 for two credentials or an unreadable body, 401 or 403 for a refused credential or origin, 404 for a route that does not exist or is not open to the credential, 413 for a body over 64 KiB, 429 for a rate limit (with a Retry-After header), and 502, 503 or 504 when the hub is unreachable or too slow, or the credential cannot be checked (Errors — gateway codes). Branch on the code, never on the status (Handling errors). An answer without the envelope (an HTML page, a plain-text status) did not come from a route: check the base URL and the path, or treat it as the service being unavailable.

Timeouts

The gateway waits 20 s on the three quote routes (the hub’s own quote deadline is 15 s) and 10 s on every other route, then answers EPX0052 (504). Give your client a longer timeout, so that the gateway’s answer, not your client, ends a slow call: the SDK waits 25 s on quotes, 12 s on reads and 15 s on submissions. An order submission (POST /order, POST /order/openfor) keeps running at the hub when your client disconnects, but not past the gateway’s 10 s. On a submission, EPX0052 means the outcome is unknown, not that the order failed: look the order up by its hubOrderId, then re-post the same body (Handling errors — a lost answer).

Value formats

The three order-id namespaces

Do not mix them.

Unknown fields

Bodies are decoded leniently: unknown JSON fields are ignored, not refused. A body that is not valid JSON never reaches the hub’s routes: its framework refuses it, EMC0028 reference Body. Valid JSON the route’s form can’t take (a wrong JSON type, for example) is EIN0001 reference body. What that implies for client-side validation, and the other things the hub deliberately does not check: Input validation.

See also