Gateway HTTP

Gateway HTTP is the HTTP surface of an Agent Gateway environment: the MCP endpoint, the REST mirror, the documents it publishes and the sign-in endpoints. Use this page when you call a gateway from your own code or need to read an error.

URLs

Every URL of an environment starts with the same base. <workspace> is your workspace's slug and <gateway> is the gateway's slug.

https://gateway.faustine.ai/<workspace>/<gateway>                  the default environment
https://gateway.faustine.ai/<workspace>/<gateway>/<environment>    any other environment

With a custom domain, your domain replaces gateway.faustine.ai/<workspace>: https://<your-domain>/<gateway>[/<environment>]. Both addresses keep working.

Path after the base Methods What it serves
/mcp POST, GET, DELETE The MCP endpoint, over Streamable HTTP. POST carries JSON-RPC. The server keeps no state between requests.
/api/<namespace>/<operation> POST, GET The REST mirror. One URL per operation.
/openapi.json GET The OpenAPI document of the environment.
/docs GET The docs page.
/skill.md GET A skill file that describes the gateway to a coding agent.
/.well-known/oauth-protected-resource GET OAuth protected resource metadata.
/.well-known/oauth-authorization-server GET OAuth authorization server metadata.
/oauth/register, /oauth/authorize, /oauth/token, /oauth/revoke The OAuth endpoints gateway users sign in through.

/openapi.json, /docs and /skill.md are public by default. When an environment's docs are not public, they require a credential and show only the operations that credential can call. See Customize the gateway docs page.

In the REST path, <namespace> is the API's namespace and <operation> is the rest of the operation key. The operation crm.contacts.create is served at /api/crm/contacts.create.

Authentication

Every request to /mcp and /api carries a bearer token.

Authorization: Bearer fik_…
Credential Token How the client gets it
API key Starts with fik_ You create the key in the portal and give it to the client. See Create an API key.
Gateway user Starts with fot_ The client obtains it from the gateway's OAuth server after the person signs in. See Create a gateway user.

A credential works on the environment it belongs to. On any other environment or gateway, the response is the same as for an unknown credential.

Sign-in with OAuth

The gateway is its own OAuth 2.0 authorization server, one per environment. A request without a valid token gets 401 with a challenge that names the metadata document:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://gateway.faustine.ai/<workspace>/<gateway>/.well-known/oauth-protected-resource"
Property Value
Client registration Dynamic, at /oauth/register. Public clients only (token_endpoint_auth_method: none).
Grant types authorization_code, refresh_token
PKCE Required, with S256.
Access token lifetime 3600 seconds
Refresh token lifetime 30 days

A session is valid only on the host it was obtained through. A token issued on gateway.faustine.ai does not work on a custom domain, and the reverse.

Failed authentication

A 401 body is JSON with a message field.

Message Cause
Invalid API key The key is unknown, or belongs to another environment or gateway.
Invalid session token The session token is unknown, or belongs to another environment, gateway or host.
API key revoked, Gateway user revoked The credential was revoked.
API key rotated and its grace period has ended The key was rotated out.
Denied (expired): API key expired The credential's Expires date has passed.
Denied (not_yet_valid): … The credential's Not before date has not been reached.
Access token expired, Session revoked The session has to be refreshed, or the person has to sign in again.

After 30 failed authentications from one IP address in a minute, every request from that address gets 429 with the code auth_throttled and a Retry-After header, until the minute ends.

Request headers

Header Required Description
Authorization Yes Bearer and the key or the session token.
Content-Type For POST with a body application/json
X-Faustine-Connection No The name of the connection to call, when the API's routing lets the caller choose. Same as the $connection input field. See Routing: fixed, dynamic and fan-out.
X-Upstream-Authorization No The caller's own credentials for your API, when the API passes credentials through. See Pass the caller's credentials through.

Response headers

Header Description
X-Faustine-Request-Id, x-request-id The ID of the request, starting with req_. Search the gateway's Logs tab by it.
X-Faustine-Manifest-Version The versions of the APIs the environment serves. It changes when the served operations change.
Retry-After Seconds to wait, on 429 responses.
Allow The accepted methods, on 405 responses.

REST requests

A REST call runs one operation. The request body is the operation's input.

Method Input Accepted for
POST A JSON object in the body. An empty body is an empty input. Every operation.
GET The query string. Read operations only. A GET to a write operation returns 405.

With GET, a query value is read as a boolean, a number, null or JSON when it looks like one, unless the operation's schema declares the field as a string. A repeated key becomes an array.

<GATEWAY_KEY> is an API key of the environment.

terminal
curl -X POST https://gateway.faustine.ai/<workspace>/<gateway>/api/crm/contacts.create \
  -H "Authorization: Bearer <GATEWAY_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"first_name": "Ada", "last_name": "Lovelace", "email": "[email protected]"}'

REST responses

A successful call returns 200 with the status and the body your API answered.

{
  "status": 201,
  "body": { "id": 42, "first_name": "Ada", "last_name": "Lovelace", "email": "[email protected]" }
}

Under fan-out routing, body is { "byConnection": [ … ] } with one entry per connection.

Errors

A failed call returns an error envelope.

{
  "error": {
    "code": "scope",
    "message": "Denied (scope): This key is not scoped for \"crm.contacts.delete\"",
    "requestId": "req_01JCD9T3W8Q2M4X6Z0V5B7N1KP"
  },
  "denyReason": "scope"
}
Field Description
error.code A stable code from the tables on this page.
error.message A sentence for a person or a model. A refusal starts with Denied (<code>):.
error.requestId The request's ID in the gateway's Logs tab.
denyReason Present when the gateway refused the call. Same value as the code.
status, body Present on upstream_error. The status and the body your API answered.

Over MCP, a failed operation is a tool result marked as an error, with the same message as its text. A request refused before any tool runs (a paused gateway, a channel or an IP restriction) is an HTTP error with the envelope.

Refused by the credential or the environment

Code Status Cause
scope 403 The operation is not in the credential's scope.
read_only 403 The credential is read-only and the operation writes.
requires_confirmation 403 The operation requires confirmation and was not confirmed: the credential is set to Refuse, or the client cannot ask the person. See Confirmation.
channel 403 The credential or the environment does not allow this channel.
ip_not_allowed 403 The caller's address is not on the allowlist.
ip_blocked 403 The caller's address is on a blocklist or belongs to a blocked country.
write_not_available 403 The API uses fan-out routing and the write is disabled or names no connection.
gateway_paused 503 The gateway is paused.

Wrong request

Code Status Cause
unknown_operation 404 No operation with that key is exposed in this environment.
method_not_allowed 405 GET on a write operation, or a method other than GET and POST.
invalid_input 400 The input is not a JSON object.
no_connection 400 The API has several connections and the request does not select one, or names one that is not available.
body_too_large 413 The body exceeds the credential's limit.

Limits

Code Status Cause
rate_limit 429 The credential's rate limit or the environment-wide rate limit was exceeded.
quota 429 The hourly or daily quota is used up.
concurrency 429 The credential has too many calls in flight.
runner_busy 429 A recipe could not start because the code runner is at capacity.
auth_throttled 429 Too many failed authentications from the caller's address.

Every 429 carries Retry-After in seconds. See Limits and quotas for the defaults.

Repeated writes

These codes exist when the environment deduplicates repeated writes. A repeat of a finished write is not an error: it returns 200 with the stored response of the first call.

Code Status Cause
idempotency_in_flight 409 The same write was sent before and has not finished, or its outcome is unknown.
idempotency_conflict 409 A write with the same identifying fields and different values ran inside the window.
idempotency_duplicate 409 The same write already ran, and its response was larger than 64 KB and was not kept.

See Repeated writes.

Your API and recipes

Code Status Cause
upstream_error 502 Your API answered with an error status or could not be reached.
auth_failed 502 The gateway could not sign in to your API with the connection's credentials.
no_credential 502 The connection has no credentials.
no_base_url 502 The connection has no base URL.
response_too_large 502 Your API's response is larger than the gateway reads.
recipe_error 422 The code of a recipe threw an error.
sandbox_limit 422 A recipe exceeded its time, memory or call limit.
recipe_http_denied 400 A recipe tried to reach a URL it is not allowed to call.
runner_unavailable 503 The code runner is not available.
internal 500 An error inside the gateway.

Next steps

Last updated November 13, 2026