Calling custom endpoints
Send a request body to a slug and let the gateway choose the provider, model and parameters.
A custom endpoint is a URL whose provider and model are configured on the gateway:
POST https://api.appaigateway.com/v1/apps/{app}/endpoints/{slug}Authentication is identical to the proxy: a gateway token with
X-App-Version, or an API key. Limits, usage and error codes are the same.
Only POST is accepted.
Request bodies
Send the body of the endpoint's request format, as the provider documents it.
You may omit model; if you send one, the gateway replaces it with the
endpoint's model, and for the Gemini formats it puts the model in the URL
instead. The endpoint's parameters are deep-merged over your body, with the
endpoint winning on conflicts, and a text endpoint's output cap is applied
like the proxy's.
| Request format | Body |
|---|---|
| OpenAI Responses | {"input": "…"} |
| OpenAI Chat Completions | {"messages": [{"role": "user", "content": "…"}]} |
| Anthropic Messages | {"max_tokens": 1024, "messages": [{"role": "user", "content": "…"}]} |
| Gemini generateContent | {"contents": [{"parts": [{"text": "…"}]}]} |
| OpenAI image generation | {"prompt": "…"} |
| OpenAI embeddings | {"input": "…"} |
| Gemini embedContent | {"content": {"parts": [{"text": "…"}]}} |
| OpenAI audio transcription | A multipart/form-data upload with a file field |
curl https://api.appaigateway.com/v1/apps/example-app-a1b2c3/endpoints/chat \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'X-App-Version: 1.4.2' \
-H 'Content-Type: application/json' \
-d '{"input":"Suggest a 500 kcal lunch."}'The response is in the serving provider's format. If a Responses endpoint falls back from OpenAI to xAI, you get xAI's Responses-style body. Both follow the same shape, but read the usage and any provider-specific fields defensively.
An Anthropic Messages endpoint sends anthropic-version: 2023-06-01 when your
request has no anthropic-version header, and yours when it does.
A Gemini speech model answers with audio only when the request asks for it
with "generationConfig": {"responseModalities": ["AUDIO"]}. Send it from
your clients or set it in the endpoint's parameters.
Streaming
Streaming works as on the proxy: set "stream": true and read the event
stream. On a Gemini generateContent endpoint, add ?alt=sse to the endpoint
URL instead, as Gemini's own API does; the gateway calls the streaming method
for you. A fallback happens only if nothing has been streamed yet.
From Swift, pass the query to the request helper rather than adding it to the URL afterwards: an App Attest proof is signed over the URL, query included. This needs the Swift package 1.6.0 or later.
let (bytes, response) = try await gateway.withAuthorizedRequest(
endpointSlug: "gemini-chat",
query: [URLQueryItem(name: "alt", value: "sse")],
body: body,
contentType: "application/json"
) { try await URLSession.shared.bytes(for: $0) }Transcription endpoints
Send an OpenAI audio-transcription multipart body. model may be omitted.
Leave response_format at its default or choose another JSON format: a
plain-text answer (text, srt or vtt) reports nothing to bill, so it is
refused with 400 invalid_request.
curl https://api.appaigateway.com/v1/apps/example-app-a1b2c3/endpoints/transcribe \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'X-App-Version: 1.4.2' \
-F file=@note.m4aWith the Swift package
let (data, response) = try await gateway.withAuthorizedRequest(
endpointSlug: "chat",
body: Data(#"{"input":"Suggest a 500 kcal lunch."}"#.utf8),
contentType: "application/json"
) { try await URLSession.shared.data(for: $0) }Pass the body to withAuthorizedRequest: when the app verifies App Attest on
every request, the request is signed over it, as described in
Per-request proof.
Errors
An unknown slug answers 404 endpoint_not_found. A method other than POST
answers 404 invalid_request. When every target in the chain fails, the last
provider's error is returned, or 502 provider_error if none could be
reached.