View Markdown

Application API

On this page

Documentation / Reference / Application API

Your application talks to Pointsman; Pointsman authenticates its virtual key, applies its controls and calls an eligible model. You supply provider credentials to the gateway, not to every application. This page explains the application-facing HTTP contract with examples you can adapt after the quickstart.

The launch scope is Chat Completions. This is not support for every endpoint or field in another provider's API. Read the compatibility matrix for provider differences and explicit refusals. The examples here are illustrative; this documentation update did not execute live-provider requests.

Base URL and authentication#

For the local quickstart, use http://localhost:8080. Use your deployment's HTTPS address outside that local setup. Every endpoint below uses a Pointsman virtual key:

http
Authorization: Bearer <your-pointsman-virtual-key>

Set these variables in a private terminal for the curl examples. Replace both placeholders before running; use a model or group your key is permitted to access.

bash
export POINTSMAN_URL='http://localhost:8080'
export POINTSMAN_KEY='<your-pointsman-virtual-key>'
export POINTSMAN_MODEL='<allowed-model-or-group>'

Do not use your provider key or dashboard password as the bearer token. Admin calls use a separate authentication surface described in the admin API. The examples use curl and jq; jq constructs JSON safely from shell variables.

Endpoints at a glance#

Method and path Result
POST /v1/chat/completions One JSON completion or an SSE stream.
GET /v1/models The caller's available models, usable groups and allowed aliases.
GET /v1/models/{id} One available entry, or 404 if it is unknown or unavailable to the caller.
POST /v1/feedback Accept feedback about an eligible outcome-learning decision.
POST /v1/quality/assessments Record typed quality evidence about a quality-guarded response, citing its X-Quality-Receipt (experimental; how-to). Returns what was stored (201 created, 200 duplicate, 409 conflicting revision); never claims a routing effect.

Responses, embeddings, audio, batch and rerank APIs are not implemented. Tool pass-through does not execute a tool or authorize the tool's eventual actions.

Create a Chat Completion#

POST /v1/chat/completions accepts Content-Type: application/json.

bash
jq -n --arg model "$POINTSMAN_MODEL" '{
  model: $model,
  messages: [
    {role: "system", content: "Explain technical concepts in plain language."},
    {role: "user", content: "What does an AI gateway do?"}
  ],
  max_tokens: 128,
  temperature: 0,
  stream: false
}' | curl --fail-with-body --silent --show-error \
  --dump-header response-headers.txt \
  "$POINTSMAN_URL/v1/chat/completions" \
  -H "Authorization: Bearer $POINTSMAN_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary @-

Requests to a live provider may incur charges. A representative response looks like this; IDs, text, model identifiers and token counts vary:

json
{
  "id": "chatcmpl-example",
  "object": "chat.completion",
  "created": 1800000000,
  "model": "support-chat",
  "choices": [
    {
      "index": 0,
      "message": {"role": "assistant", "content": "An AI gateway manages your application's calls to AI models."},
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 25, "completion_tokens": 18, "total_tokens": 43}
}
Response field How to use it
id, object, created Completion identifier, object kind and Unix timestamp in seconds. Use X-Request-ID for gateway investigation.
model The response's request-facing model name; it can be a group. Inspect served-model evidence separately.
choices[0].message Assistant message. For supported tool requests it can contain tool calls instead of ordinary text.
choices[0].finish_reason Why generation ended; distinguish a normal stop, length exhaustion and tool calls where supported.
usage Token accounting when available. Provider usage and estimates have different certainty, especially after interruption.
service_tier Optional provider-reported processing tier when returned.
guardrail_results Optional gateway extension when the configured response reporting includes it.

On synchronous provider-served responses, X-Served-Provider and X-Provider-Model help identify what answered. Cache hits and live streams have different header availability; see the header reference. Do not assume an absent header has a default value.

Request fields and boundaries#

Field Meaning and important boundary
model Concrete model, alias or routing group. Prefer an explicit value in a first integration; omission depends on configured resolution/defaults.
messages Required nonempty conversation. Use lowercase supported roles and the content shape for that role. Text is supported; image input is refused in the v1 exact-tokenizer profile.
stream Omitted/false gives JSON; true gives SSE.
max_tokens / max_completion_tokens Positive output cap. They are aliases; conflicting values are refused. An omitted cap is supplied and bounded by gateway/model/context limits.
temperature, top_p, stop Sampling and stop controls, subject to selected model and adapter support. An omitted temperature is not automatically zero.
seed, presence_penalty, frequency_penalty Adapter-dependent controls. Check the adapter matrix before relying on them.
logit_bias, logprobs, top_logprobs OpenAI-compatible adapter controls. top_logprobs requires logprobs: true; logprob requests bypass cache/coalescing.
tools, tool_choice, parallel_tool_calls, function strict OpenAI-compatible pass-through; Anthropic and Ollama adapters currently refuse these tool requests.
service_tier Processing-tier pass-through where supported, not a routing strategy.
n Omitted or 1. Multiple choices are not supported.
response_format, reasoning_effort, thinking Refused. Do not infer structured-output or reasoning-control support from the API's shape. A model row may fix an effort the operator chose; the client cannot change it.
user, metadata, store, prompt_cache_key, safety_identifier, stream_options Tolerated and dropped. Acceptance does not mean the provider received them or that they were stored.

The compatibility matrix includes the remaining explicitly refused controls. The adapter matrix explains forwarding differences. Unknown fields are not a general pass-through contract. Context checks use the configured tokenizer mode and model metadata; chat framing and tool scaffolding still limit provider-exact counting claims. In exact-tokenizer mode the count is taken after model resolution, with the encoding of the model or group that will serve, so an unknown model behaves as the key's resolution policy says and an omitted model is resolved by the blank-model path (key default, tenant default, semantic group, mode tier, cheapest allowed), the same as in estimate mode, unless the key or the gateway is set to refuse it (400 model_required).

Request headers#

Use X-Request-ID to supply a correlation ID (1–128 characters from letters, digits, ., _ and -), or let the gateway generate one. Use X-Cache-Control: no-cache when deliberately bypassing both cache tiers, for example while checking provider connectivity. This can increase provider calls and charges.

Other cache, guardrail and routing-related headers are described in the header reference and the feature guides. These headers do not bypass a virtual key's permissions or spending controls.

Stream a completion#

Use the same endpoint with stream: true. curl --no-buffer displays data as it arrives instead of buffering output:

bash
jq -n --arg model "$POINTSMAN_MODEL" '{
  model: $model,
  messages: [{role: "user", content: "Explain a gateway in three short sentences."}],
  max_tokens: 128,
  stream: true
}' | curl --fail-with-body --silent --show-error --no-buffer \
  "$POINTSMAN_URL/v1/chat/completions" \
  -H "Authorization: Bearer $POINTSMAN_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary @-

Consume SSE records, not arbitrary TCP chunks. A text event has a chat.completion.chunk object with choices[].delta; append content deltas to build the answer. Handle empty deltas, finish information and usage separately. A normal stream terminates with data: [DONE].

text
data: {"id":"chatcmpl-example","object":"chat.completion.chunk","created":1800000000,"model":"support-chat","choices":[{"index":0,"delta":{"content":"An AI gateway"},"finish_reason":null}]}

data: [DONE]

This abbreviated illustration omits intervening chunks. Tool calls are emitted as an assembled chunk when complete, not progressive argument fragments. The gateway owns upstream usage requests; sending stream_options does not change that. For a provider configured as a registry row, upstream stream usage is requested only when the operator set the row's streamUsage quirk; otherwise the stream carries no usage chunk.

Check both the initial HTTP status and error payloads arriving after the stream starts. HTTP 200 cannot become a different status after headers have been sent. An interrupted stream may contain partial output and estimated usage. Avoid blindly retrying it as if no provider work occurred.

Discover available models#

bash
curl --fail-with-body --silent --show-error \
  "$POINTSMAN_URL/v1/models" \
  -H "Authorization: Bearer $POINTSMAN_KEY" | jq .

The response is a list object with data entries. A concrete model uses object: "model"; a routing group uses object: "model-group". Entries have id, object, created and owned_by. Optional metadata includes family, tier, cost_per_1k, modality, context, params, tags, aliases, deprecated and alias_for. Omitted metadata means it was not supplied, not that a capability or limit is unlimited. cost_per_1k is configured input pricing metadata; it is not a complete input/output price quote or live provider invoice.

Retrieve a single entry by URL-encoding its identifier:

bash
MODEL_PATH=$(jq -rn --arg id "$POINTSMAN_MODEL" '$id | @uri')
curl --fail-with-body --silent --show-error \
  "$POINTSMAN_URL/v1/models/$MODEL_PATH" \
  -H "Authorization: Bearer $POINTSMAN_KEY"

Discovery is scoped to the caller. A 404 on this endpoint does not distinguish an unknown identifier from one the key cannot access. Listing a model is not proof that the provider is healthy or that every optional request control is supported.

Send outcome feedback#

POST /v1/feedback is for the outcome-learning router. A weighted-random or direct model request does not become trainable just because you send a rating.

For an eligible decision, save X-Decision-Receipt from the completion response and send it as decision_id. Prefer this signed receipt to the bare X-Decision-Id when using multiple gateway instances. Use the same virtual key that made the call.

bash
export POINTSMAN_DECISION='<X-Decision-Receipt-from-the-response>'
jq -n --arg decision "$POINTSMAN_DECISION" '{
  decision_id: $decision,
  rating: 1,
  revision: 0
}' | curl --fail-with-body --silent --show-error \
  "$POINTSMAN_URL/v1/feedback" \
  -H "Authorization: Bearer $POINTSMAN_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary @-
Field Contract
decision_id Required nonblank signed receipt or eligible decision ID. Ownership and age are checked.
rating Integer: 1 for positive or −1 for negative. Zero is refused. Required unless retract is true, and refused with it.
revision Optional integer, defaults to 0; range 0 through 9,007,199,254,740,991. Reuse a revision on a retry; increase it for an edited rating or a retraction.
retract Optional boolean. true withdraws the decision's rating (send it with a higher revision and no rating); the decision returns to its unrated reward. A retraction without a revision of at least 1 is refused with 400. Withdrawing the only quality of a rate-composition decision is recorded and changes nothing, because such a decision has no unrated reward to return to. Not available for decisions made before the learning semantics changed (17 October 2026).

A rating revises the decision it names; it does not count as an extra observation.

A valid submission normally returns 202 {"accepted":true}. This acknowledges submission, not proof that a policy changed. Unknown, expired or ineligible provenance can be ignored without revealing whether someone else's decision exists. A disabled feedback service can return 503; feedback rate limits can return 429 with Retry-After. Use your actual task result as feedback, such as whether an extraction passed validation. How learning uses feedback.

Errors and retries#

Most gateway errors use an error object with message and type; code and param are included where provided. Parse defensively rather than requiring every field. For example, an unsupported control can identify both the field and the unsupported_request_control code.

Status or situation What to investigate
400 Invalid shape, unsupported control, invalid token cap or an incompatible request. Correct it before retrying.
401 / 403 Key validity, environment, authorization or scope. Dashboard credentials are not application credentials.
402 Spending restrictions. Inspect the error and effective limits; retries alone do not create budget.
404 on model lookup Unknown or unavailable model. Recheck discovery with the same key.
429 Rate/capacity refusal. Honor Retry-After when present and reduce concurrency or request rate.
503 budget_recovering The budget this request is charged to is held until its balance is established: the counter store is starting or activating a new budget generation (transient: retry with backoff, usually clears in seconds), or the operator must attest it after a counter-store loss or a declared database restore (retries will NOT clear it; only the operator's recovery does). The refusal happens before any provider call. Bound your retries; do not retry indefinitely.
5xx Inspect the error code, request ID and dependency state. Budget recovery and upstream outages require different responses.
Error after SSE begins Preserve partial output and error details; initial HTTP 200 is not a successful completion.

These categories are not an exhaustive error-code catalogue. Use bounded retries with backoff for transient failures, and consider whether the upstream may already have processed the request. This page does not promise exactly-once completion or idempotent billing for a retried chat request.

When reporting an issue, include a redacted request shape, gateway version, request ID, status/error code and whether it streamed or hit cache. Exclude credentials and sensitive prompt content. Request investigation.

Implementation references#

The contract above was checked against the current chat request, chat response, model entry, feedback request and the controllers. Runtime/provider verification remains part of release qualification.

Pointsman v1 candidate documentation Source: 0e09f5e7

Search guides, reference pages and architecture.

Documentation

Open full-size image