InferNode API
Base path: https://api.<tu-dominio>/infernode/v1. Authentication with Authorization: Bearer sk-saptiva-.... Compatible with the OpenAI SDK (see Use the API from code).
Inference
| Method and path | Description |
|---|---|
POST /v1/chat/completions | Chat. Fields: model, messages, stream, temperature, top_p, max_tokens, n, stop, presence_penalty, frequency_penalty, seed, tools, tool_choice, response_format, logprobs, top_logprobs. The reasoning parameters thinking_token_budget, chat_template_kwargs (enable_thinking, reasoning_budget) and reasoning (effort) are forwarded to the model without being interpreted (X-Saptiva-Passthrough header). With stream: true it responds over SSE with the OpenAI chunk format. |
POST /v1/embeddings | Vectors. model, input (string or list), dimensions (up to the model's maximum, 4096 for the platform's model), encoding_format (float or base64). |
POST /v1/images/generations | Generates images. Body: preset (name of the image model in the Catalog), prompt (up to 4096 characters), n (1 to 4), size (default 1024x1024). Returns the result, or a job with job_id if the generation is asynchronous. Counts against the images-per-minute limit. |
GET /v1/images/generations/{job_id} | Status and result of the job. |
POST /v1/guard | Evaluates a text against the risk categories. |
GET /v1/guard/events | Recorded evaluations of your Client. |
Request and response example
The examples call by alias, which is the recommended way: the exact Catalog name is accepted too, but it changes when the model is updated. The response returns in model the model that answered, not the alias you called with.
curl https://api.<tu-dominio>/infernode/v1/chat/completions -i \
-H "Authorization: Bearer sk-saptiva-..." -H "Content-Type: application/json" \
-d '{"model": "Saptiva Turbo", "messages": [{"role": "user", "content": "Hola"}], "max_tokens": 64}'
HTTP/1.1 200 OK
X-Request-Id: req_01J9X4M2K7
X-RateLimit-Remaining-Requests: 58
X-RateLimit-Remaining-Tokens: 199872
X-Request-Cost: 0.0004
X-Credits-Remaining: 1249.31
{
"id": "chatcmpl-...",
"object": "chat.completion",
"model": "Qwen3.6 35B A3B (FP8)",
"choices": [{ "index": 0, "message": { "role": "assistant", "content": "Hola, ¿en qué puedo ayudarte?" }, "finish_reason": "stop" }],
"usage": { "prompt_tokens": 9, "completion_tokens": 11, "total_tokens": 20 }
}
An error uses the OpenAI envelope with request_id:
{ "error": { "type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Token limit exceeded, resets in 42s", "request_id": "req_01J9X4M2K7" } }
Batches
Asynchronous requests in a file, compatible with the OpenAI Batch API. Guide in Process requests in batches. If the installation does not have them enabled, these routes respond 404.
| Method and path | Description |
|---|---|
POST /v1/files | Uploads the input file. Multipart with purpose=batch (the only accepted value) and file. Returns an object with id, bytes, filename, purpose, status and created_at. The same content uploaded twice returns the existing file, with the X-Saptiva-Deduplicated-From header |
GET /v1/files | Files of the organization |
GET /v1/files/{file_id} | Metadata of a file |
GET /v1/files/{file_id}/content | Downloads the bytes. Responds with X-Saptiva-Content-SHA256. It is the only way to download: there are no temporary links |
DELETE /v1/files/{file_id} | Deletes a file. An input file used by a live batch responds 400 file_in_use |
POST /v1/batches | Creates the batch. Body: input_file_id, endpoint (/v1/chat/completions or /v1/embeddings), completion_window (only "24h", with no delivery promise) and optional metadata |
GET /v1/batches | Batches of the organization. limit from 1 to 100 (20 by default) and after with a batch id as the cursor |
GET /v1/batches/{batch_id} | Status and result of the batch |
POST /v1/batches/{batch_id}/cancel | Cancels. From finalizing or a terminal state it responds 400 batch_not_cancellable |
The batch object includes status, input_file_id, output_file_id, error_file_id, endpoint, model, completion_window, metadata, request_counts (total, completed, and failed, which adds up the failed, cancelled and expired lines), errors.data, usage when it finishes, and the timestamps of each transition (created_at, in_progress_at, expires_at, finalizing_at, completed_at, failed_at, expired_at, cancelling_at, cancelled_at).
errors.data carries the causes when the whole file fails and, when someone other than its owner cancelled the batch, a cancelled_by_org_admin or cancelled_by_platform_admin entry.
Statuses: validating, in_progress, finalizing, cancelling, and the terminal ones completed, failed, cancelled and expired.
The output file contains only the lines that finished successfully; the rest go to the error file. Input and output files expire after 30 days by default, with the date in expires_at.
Each line is billed as the equivalent call, with no discount. The transaction carries the endpoint marked, visible in last_event.endpoint of GET /v1/billing/balance (/v1/chat/completions:batch). The lines do not consume the per-minute limits; the calls in this section do.
Models
| Method and path | Description |
|---|---|
GET /v1/models | Models available for the key. |
GET /v1/models/{name} | Detail: type, provider, capabilities, context_window, max_output_tokens, pricing (input, output, unit, currency) and deprecation (deprecated_at, retires_at). With an alias, X-Alias-Of header. |
GET /v1/models/aliases | Public aliases and the model they point to. |
Account and keys
| Method and path | Description |
|---|---|
GET /v1/me | org, user, membership, plan (with is_billing_exempt and has_rate_limits) and the api_key you called with. |
GET /v1/me/orgs | Organizations you belong to. |
GET /v1/me/api-keys | The user's keys (without the secret). |
POST /v1/me/api-keys | Create a key. The secret is shown only once. |
POST /v1/me/api-keys/{id}/rotate | Rotate: new key, the previous one stops working. |
DELETE /v1/me/api-keys/{id} | Revoke. |
Usage
| Method and path | Description |
|---|---|
GET /v1/billing/balance | credits_remaining, initial_credits, spending_caps, usage_this_month, last_event; is_billing_exempt indicates whether the plan deducts credits. |
GET /v1/billing/usage?period=AAAA-MM | total_requests, total_tokens_in, total_tokens_out, total_cost, by_model, by_api_key, daily_breakdown (and by_user for administrators). |
GET /v1/billing/transactions | Credit transactions. |
Response headers
X-Request-Id, X-RateLimit-Limit-Requests, X-RateLimit-Remaining-Requests, X-RateLimit-Reset-Requests, X-RateLimit-Limit-Tokens, X-RateLimit-Remaining-Tokens, X-RateLimit-Reset-Tokens, X-Request-Cost, X-Credits-Remaining, X-Credits-Warning, X-Model-Deprecated, X-Model-Retires-At, X-Alias-Of, X-Saptiva-Passthrough, X-Saptiva-Model-Defaults; on a 429, also Retry-After. In streaming responses the token headers are not sent (the count happens after the header is emitted). Meaning in InferNode.
Errors
Extended OpenAI envelope: {"error": {"type", "code", "message", "param", "request_id", "details"}}. code carries the module as a prefix when applicable (identity.invalid_token, identity.org_suspended) or is flat (model_not_found, rate_limit_exceeded, insufficient_credits, parameter_not_supported). Types: invalid_request_error, authentication_error, permission_error, not_found_error, billing_error, rate_limit_error, provider_error, maintenance_error, internal_error. A 429 includes details.dimension (rpm, rpd, tpm, tpd, ipm). Details in Error codes.
The platform administration operations (adding models, per-Client limits, credits, auditing) are under /v1/admin/* and /v1/billing/admin/*, reserved for the operator.