# Gateway API Reference The gateway proxies requests from your application through OneHazel to supplier APIs. It handles authentication, schema translation, rate limiting, and circuit breaking automatically. **Endpoint:** `POST /functions/v1/gateway` **Authentication:** `Authorization: Bearer oh_live_...` ## How it works 1. You send an operation name and parameters in OneHazel's canonical format 2. The gateway looks up the connection and its connector blueprint 3. Parameters are translated from canonical to provider field names via the schema mapping 4. Authentication credentials are applied (decrypted from the connection config) 5. The request is sent to the provider's API endpoint 6. The response is translated back to canonical format 7. The call is logged to `gateway_logs` ## Request ``` POST /functions/v1/gateway ``` | Field | Type | Required | Description | |---|---|---|---| | `connectionId` | string | Yes | ID of an active connection | | `operation` | string | Yes | Operation name in `entity.action` format | | `params` | object | No | Parameters in canonical format | ### Operation format Operations use a dot-notation format: `entity.action`. The action keyword determines the HTTP method: | Action keyword | HTTP Method | |---|---| | `verify`, `check`, `get`, `list`, `fetch`, `read`, `search`, `find`, `status`, `balance` | GET | | `create`, `deposit`, `submit`, `send`, `initiate`, `register`, `start` | POST | | `update`, `modify`, `edit` | PATCH | | `replace`, `set` | PUT | | `delete`, `remove`, `cancel`, `revoke` | DELETE | If no matching keyword is found, the default method is `POST`. ### Example: Verify a player's identity ```bash curl -X POST https://api.onehazel.com/gateway \ -H "Authorization: Bearer oh_live_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "connectionId": "conn_abc123", "operation": "applicant.verify", "params": { "externalUserId": "player_12345", "firstName": "James", "lastName": "Wilson", "dateOfBirth": "1992-03-15", "country": "GBR" } }' ``` ### Example: Create a payment ```bash curl -X POST https://api.onehazel.com/gateway \ -H "Authorization: Bearer oh_live_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "connectionId": "conn_stripe_xyz", "operation": "payment.create", "params": { "amount": 5000, "currency": "gbp", "description": "Player deposit", "metadata": { "player_id": "player_12345" } } }' ``` ### Example: Get account balance ```bash curl -X POST https://api.onehazel.com/gateway \ -H "Authorization: Bearer oh_live_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "connectionId": "conn_payment_456", "operation": "account.balance", "params": {} }' ``` ## Response ### Success ```json { "success": true, "data": { "id": "pi_3abc123", "status": "succeeded", "amount": 5000, "currency": "gbp" }, "latencyMs": 342 } ``` The `data` field contains the provider's response translated to canonical field names via the connector's schema mapping. Fields without a mapping are passed through unchanged. ### Provider error When the provider returns a non-2xx status: ```json { "success": false, "error": { "code": "PROVIDER_ERROR", "message": "Provider returned 422" }, "data": { "error": "Invalid card number" }, "latencyMs": 156 } ``` HTTP status: `502` ## Schema translation The gateway performs bidirectional field name translation using the connector's `schemaMap`: - **Outbound** (canonical to provider): Your `params` fields are translated to provider field names before sending the request - **Inbound** (provider to canonical): The provider's response fields are translated back to canonical names Fields without a mapping in either direction are passed through unchanged. ## Authentication Connection credentials are stored encrypted (AES-256-GCM) and decrypted at request time. The gateway applies auth based on the connector's OpenAPI `securitySchemes`: | Security Scheme | How it's applied | |---|---| | `apiKey` (header) | Sets the specified header name with the API key value | | `apiKey` (query) | Adds the key as a query parameter | | `http` (bearer) | Sets `Authorization: Bearer ` | | `http` (basic) | Sets `Authorization: Basic ` | | HMAC | Signs the request body with HMAC-SHA256, sets `X-Signature` and `X-Signature-Algorithm` headers | If no `securitySchemes` are defined in the OpenAPI spec, the gateway falls back to sending a Bearer token using the first available credential from the connection config. ## Circuit breaker The gateway includes an in-memory circuit breaker per provider. If a provider returns too many `5xx` errors, the circuit opens and subsequent requests are rejected immediately with: ```json { "success": false, "error": { "code": "CIRCUIT_OPEN", "message": "Provider circuit breaker is open — too many recent failures. Retry in 30s." }, "latencyMs": 1 } ``` HTTP status: `503`, with `Retry-After: 30` header. Successful responses reset the circuit breaker. ## Operation matching The gateway matches your `operation` string to an OpenAPI path in the connector's spec using a scoring algorithm: 1. The entity name (first part before the dot) is matched against URL path segments 2. The action keyword is matched against HTTP methods and path/summary/operationId 3. The highest-scoring match is selected If no match is found: ```json { "success": false, "error": { "code": "OPERATION_NOT_FOUND", "message": "No matching endpoint found for operation \"foo.bar\"" } } ``` ## Events Every gateway call emits an event: - `gateway.request.completed` — for successful calls (provider returned 2xx) - `gateway.request.failed` — for failed calls (provider returned non-2xx) These events can trigger workflows. ## Error codes | HTTP Status | Error Code | Description | |---|---|---| | `400` | `MISSING_FIELDS` | `connectionId` or `operation` is missing | | `400` | `CONNECTION_INACTIVE` | Connection exists but is not active | | `400` | `BLUEPRINT_NO_SPEC` | Connector has no OpenAPI spec | | `401` | `AUTH_MISSING` | No `Authorization` header | | `401` | `AUTH_INVALID` | API key not recognised | | `401` | `AUTH_REVOKED` | API key has been revoked | | `404` | `CONNECTION_NOT_FOUND` | Connection not found or belongs to another operator | | `404` | `CONNECTOR_NOT_FOUND` | Connector blueprint not found | | `404` | `OPERATION_NOT_FOUND` | No endpoint matches the operation | | `405` | `METHOD_NOT_ALLOWED` | Only POST is accepted | | `429` | `RATE_LIMITED` | Rate limit exceeded for `gateway:execute` | | `502` | `PROVIDER_ERROR` | Provider returned a non-2xx response | | `503` | `CIRCUIT_OPEN` | Circuit breaker is open | | `500` | `INTERNAL_ERROR` | Server error |