Create a chat completion

POST /v1/chat/completions

Generates a model response for the given conversation. Supports streaming via stream: true (SSE). Non-streaming responses include a _devup billing metadata object.

Authentication

Bearer API key required.

Request body — Required

application/json

ChatCompletionRequest

ChatCompletionRequest

{
  "model": "deepseek-ai/DeepSeek-V4-Pro",
  "messages": [
    {
      "role": "user",
      "content": "Hello from Algeria!"
    }
  ],
  "max_tokens": 256,
  "stream": false
}

Responses

HTTP 200

Successful chat completion (non-streaming).

application/json

ChatCompletionResponse

ChatCompletionResponse

{
  "id": "chatcmpl-79037612-d7c2-43e0-8494-c560f97c61ea",
  "object": "chat.completion",
  "created": 1700000000,
  "model": "deepseek-ai/DeepSeek-V4-Pro",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Hello! How can I help you today?"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 10,
    "completion_tokens": 8
  },
  "_devup": {
    "request_id": "req_9fd8ddec5b2149539860a86dccba58cf"
  }
}

text/event-stream

string

Server-Sent Events stream of chat completion chunks. Every chunk carries the same id (chatcmpl- followed by a UUID). When the model completes its reply, the last chunk has an empty choices array and carries usage; no other chunk carries usage. The data: [DONE] terminal event may not be present in every stream.

HTTP 400

Invalid request body or parameters.

application/json

ErrorResponse

ErrorResponse

Missing model field
{
  "error": {
    "message": "The \"model\" field is required.",
    "type": "devup_error",
    "code": "missing_model"
  }
}
Messages array too large
{
  "error": {
    "message": "messages array exceeds the maximum of 512 entries.",
    "type": "devup_error",
    "code": "payload_too_large"
  }
}
max_tokens above the model's max_output_tokens (N here)
{
  "error": {
    "message": "max_tokens must be between 1 and N.",
    "type": "devup_error",
    "code": "invalid_max_tokens"
  }
}
Model or feature served on /v1/responses only
{
  "error": {
    "message": "This model is served on /v1/responses and does not support Chat Completions. Send the same request to /v1/responses.",
    "type": "devup_error",
    "code": "use_responses_api"
  }
}
The model is served on another endpoint (not billed)
{
  "error": {
    "message": "This model is served on /v1/images/generations, not on /v1/chat/completions. Send the request to /v1/images/generations.",
    "type": "devup_error",
    "code": "wrong_endpoint"
  }
}
The model does not support tool calling
{
  "error": {
    "message": "This model does not support tool calling. Remove tools and tool_choice from the request.",
    "type": "devup_error",
    "code": "tools_not_supported"
  }
}
The model needs a final user message
{
  "error": {
    "message": "This model needs the conversation to end with a user message.",
    "type": "devup_error",
    "code": "conversation_must_end_with_user"
  }
}
A message has empty content
{
  "error": {
    "message": "A message in the request has empty content, which this model does not accept. Give every message non-empty content.",
    "type": "devup_error",
    "code": "empty_message_content"
  }
}
A feature in the request is not available on this model
{
  "error": {
    "message": "This model does not support a feature used in the request. Check the model page for what it supports.",
    "type": "devup_error",
    "code": "feature_not_supported"
  }
}
The model does not support the requested response_format
{
  "error": {
    "message": "This model does not support the requested response_format. Remove response_format, or check the model page for the formats it supports.",
    "type": "devup_error",
    "code": "response_format_not_supported"
  }
}
The model rejected the request
{
  "error": {
    "message": "The model rejected the request. Check the messages and parameters against the API reference.",
    "type": "devup_error",
    "code": "invalid_request_error"
  }
}

HTTP 401

Missing, empty, or revoked API key. This response covers three distinct codes depending on the authentication path: - missing_api_key: Authorization header absent or Bearer token is empty. On GET /v1/models, GET /v1/models/{model}, GET /v1/me and GET /v1/me/avatar, which also accept the x-api-key header, the message is "Provide your API key as: Authorization: Bearer sk-devup-..., or in the x-api-key header." - invalid_api_key: Key not found, deactivated, or not valid. - token_revoked: The scoped JWT credential has been explicitly revoked.

application/json

ErrorResponse

ErrorResponse

Authorization header absent or empty Bearer token
{
  "error": {
    "message": "Provide your API key as: Authorization: Bearer sk-devup-...",
    "type": "devup_error",
    "code": "missing_api_key"
  }
}
Key not found, deactivated, or not valid
{
  "error": {
    "message": "The API key provided is invalid or has been deactivated.",
    "type": "devup_error",
    "code": "invalid_api_key"
  }
}
Scoped JWT credential has been explicitly revoked (scoped-token auth only)
{
  "error": {
    "message": "This scoped token has been revoked.",
    "type": "devup_error",
    "code": "token_revoked"
  }
}

HTTP 402

DZD balance depleted or scoped credential budget exhausted. - insufficient_balance: The DEVUP account has insufficient available balance. Also returned on POST /v1/chat/completions and POST /v1/responses for a request with a non-empty tools array that the balance does not cover in full. - budget_exhausted: The scoped credential has reached its configured budget. This code is never returned for unrestricted master API keys.

application/json

ErrorResponse

ErrorResponse

DEVUP account has insufficient available balance
{
  "error": {
    "message": "Your balance is depleted. Top up at https://devupai.com/dashboard/billing.",
    "type": "devup_error",
    "code": "insufficient_balance"
  }
}
Scoped credential budget exhausted (scoped-token auth only)
{
  "error": {
    "message": "Scoped token budget has been exhausted.",
    "type": "devup_error",
    "code": "budget_exhausted"
  }
}

HTTP 403

Account suspended or scoped credential does not permit the requested model. - account_suspended: The DEVUP account is suspended; all requests are blocked. - model_not_allowed: The scoped credential does not grant access to the requested model. This code is never returned for unrestricted master API keys. - scoped_token_not_allowed: On GET /v1/me and GET /v1/me/avatar, which accept account API keys (sk-devup-...) only, a scoped token was sent.

application/json

ErrorResponse

ErrorResponse

DEVUP account is suspended
{
  "error": {
    "message": "Account suspended. Contact support.",
    "type": "devup_error",
    "code": "account_suspended"
  }
}
Scoped credential does not permit the requested model (scoped-token auth only)
{
  "error": {
    "message": "This scoped token does not grant access to the requested model.",
    "type": "devup_error",
    "code": "model_not_allowed"
  }
}

HTTP 404

The requested model identifier was not found in the catalog. It is not retryable unless the model identifier is changed.

application/json

ErrorResponse

ErrorResponse

Model not found in catalog
{
  "error": {
    "message": "The requested model was not found.",
    "type": "devup_error",
    "code": "model_not_found"
  }
}

HTTP 429

Too many requests. error.code is rate_limit_exceeded (your account's per-minute limit), model_at_capacity (the model is momentarily at capacity; Retry-After: 5 and retry-after-ms: 5000, no X-RateLimit-* headers; the OpenAI and Anthropic SDKs retry it automatically), concurrency_limit_exceeded, tpm_limit_exceeded, or flex_capacity_unavailable. Wait the number of seconds in Retry-After before retrying.

application/json

ErrorResponse

ErrorResponse

Your account's per-minute limit is reached
{
  "error": {
    "message": "Rate limit exceeded. Please slow down your requests and try again shortly.",
    "type": "devup_error",
    "code": "rate_limit_exceeded"
  }
}
The model is momentarily at capacity
{
  "error": {
    "message": "This model is currently at capacity. Retry in a few seconds.",
    "type": "devup_error",
    "code": "model_at_capacity"
  }
}

HTTP 502

The model could not complete the request this time. Retry the request. A request that the model rejects is never returned as 502: it returns 400 with a specific code, such as tools_not_supported, conversation_must_end_with_user, empty_message_content, feature_not_supported, response_format_not_supported or invalid_request_error. - DEVUP_COMPUTE_ERROR: The model returned an empty or unreadable response, or could not complete the request this time. - response_truncated: The response stream was cut off before completing.

application/json

ErrorResponse

ErrorResponse

The model could not complete the request
{
  "error": {
    "message": "The model could not complete this request. Retry it; retrying usually succeeds.",
    "type": "devup_error",
    "code": "DEVUP_COMPUTE_ERROR"
  }
}
Response was cut off before completing
{
  "error": {
    "message": "The response was cut off before completing. Retrying will produce a complete response.",
    "type": "devup_error",
    "code": "DEVUP_COMPUTE_ERROR"
  }
}

HTTP 503

Requests are temporarily paused or the requested model is temporarily unavailable. Retry according to the delay communicated in Retry-After and/or retry-after-ms when present.

application/json

ErrorResponse

ErrorResponse

Requests are paused for a few seconds
{
  "error": {
    "message": "Requests are paused for a few seconds. Retry after the delay in the Retry-After header.",
    "type": "devup_error",
    "code": "service_unavailable"
  }
}
The requested model is temporarily unavailable
{
  "error": {
    "message": "The requested model is temporarily unavailable. Retry shortly.",
    "type": "devup_error",
    "code": "model_unavailable"
  }
}