Skip to content

DeepSeek V4.1 / V4

Call DeepSeek V4.1 and V4 through OpenAI Chat Completions, OpenAI Responses, or Anthropic Messages.

ItemValue
Base URLhttps://api.hop-base.com/v1
ChatPOST /v1/chat/completions
ResponsesPOST /v1/responses
Anthropic MessagesPOST /v1/messages

Authenticate with a Bearer key and use the exact model ID returned by GET /v1/models. On /v1/messages, the x-api-key header also works.

curl https://api.hop-base.com/v1/chat/completions \
  -H "Authorization: Bearer sk-your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4-pro-202606",
    "messages": [{
      "role": "user",
      "content": "Summarize this quarter'\''s risks in five bullets."
    }]
  }'

Models

Model IDContextMax output tokens per call
deepseek-v4.1-flash1M393,216
deepseek-v4-pro-2026061,048,576393,216
deepseek-v4-flash-2026051M384,000

V4.1 Flash returns its thinking in reasoning_content. It is billed against DeepSeek's official price and follows the official peak/off-peak schedule; see Peak and off-peak pricing.

All three models are in the DeepSeek group, so one key reaches all of them.

The short names are not callable.

Only the IDs in the table above are production models. Read the exact ID from GET /v1/models instead of shortening it.

These short names all return the same 404 model_not_found and never name a replacement ID: deepseek-v4-flash, deepseek-v4-pro, deepseek-chat, deepseek-reasoner, and deepseek-flash (DeepSeek's own short name for V4.1 Flash). The message is localized by the request's Accept-Language, English by default:

The current group does not support the requested model: <model>

Peak and off-peak pricing

deepseek-v4.1-flash follows DeepSeek's official peak/off-peak schedule, stated in Beijing time (UTC+8).

  • Peak: Monday to Friday, 09:00–12:00 and 14:00–18:00.
  • Off-peak: every other hour, including nights, the midday gap between the two windows, and the whole weekend.
  • Off-peak unit prices for input, cached input and output are all halved.
  • A window includes its opening minute and excludes its closing minute: 09:00:00 is already peak, 12:00:00 is already off-peak.

A request is priced by the moment it finishes, not the moment it starts. One that begins at 17:59 and ends at 18:01 is billed entirely at the off-peak rate; one that begins at 08:59 and ends at 09:01 is billed entirely at the peak rate.

A single request always carries exactly one unit price and is never split across a boundary. That is why two usage records a minute apart can show different unit prices for the same model. The rates that apply to your key are in the signed-in model catalog.

Endpoint and request parameters

POST /v1/chat/completions, POST /v1/responses and POST /v1/messages all work for all three models, and streaming works normally on each. Codex CLI uses Responses; Claude Code uses Anthropic Messages, covered in Claude Code and Anthropic Messages.

  • Fill-in-the-middle (FIM) completion is not available: it lives on a path HopBase does not route.
  • Prefix continuation is available; see Prefix continuation.

The table covers POST /v1/chat/completions. The gateway only rejects empty messages; every other limit comes from the model service.

ParameterRequiredType & limitsDefaultDescription
modelRequiredOne of the three IDs above—Exact match; short names return 404
messagesRequiredNon-empty array—role values below
max_tokensOptionalNon-negative integer; ceiling in ModelsService defaultShared by thinking and answer
temperatureOptionalNumber 0–2Service default—
thinkingOptional{"type": …}On for V4.1 FlashValues below
reasoning_effortOptionallow / medium / high work as testedService defaultApplies only when thinking is on
tools, tool_choiceOptionalAs in OpenAIautoSee Tool calling
streamOptionalBooleanfalsetrue returns server-sent events
stream_options.include_usageOptionalBooleanfalseMust be true to get usage when streaming
prefixOptionalBooleanfalsePrefix continuation
image_url.urlOptionaldata: URI or https:// URL—deepseek-v4.1-flash only
  • messages[].role is system / user / assistant / tool / developer.
  • thinking.type is enabled / disabled / adaptive; other values (such as auto) return 400.
  • A negative max_tokens returns 400; a value above the ceiling is not rejected and output is cut silently (see Reasoning output).
  • stream_options.include_usage does not affect billing.
  • prefix goes only on the last assistant message.
  • With image_url.url, the whole request body is ≤ 60 MB.

Error text quoted from production records (2026-09):

400 missing messages field                   messages missing (gateway)
400 messages must not be an empty array      messages empty (gateway)
400 expected a value <= 2                    temperature above 2

On /v1/responses, output is capped with max_output_tokens, which must be 1–393,216. temperature is again 0–2, and a request that sets caching must also set store: true. Above the cap:

400 max_output_tokens must be less than or equal to 393216

For every parameter, see the Chat Completions API reference and pick the DeepSeek model family.

Image input

deepseek-v4.1-flash reads images natively, on this same endpoint, in the standard OpenAI content-part form. image_url.url takes either a data: URI or a publicly reachable https:// URL, and several images may travel in one message.

The whole request body is capped at 60 MB. Base64 adds about a third, so the images together must stay under roughly 45 MB; send large images as https:// URLs. Above the cap:

413 Request body exceeds the size limit (60 MB)

Images are ordinary input: they are counted in prompt_tokens.

V4 Pro and V4 Flash do not accept images.

deepseek-v4-pro-202606 and deepseek-v4-flash-202605 cannot see images. A request that carries one is rejected with 400 before it reaches the model and is not billed, on Chat Completions, Responses and Anthropic Messages alike. That includes screenshots pasted into Claude Code and image files it reads; use deepseek-v4.1-flash for anything with images.

400 Model deepseek-v4-pro-202606 does not accept image input. Remove the image from the request, including earlier turns of the conversation, or use a model that supports images.
{
  "model": "deepseek-v4.1-flash",
  "messages": [
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "What is in each of these two images?" },
        { "type": "image_url", "image_url": { "url": "data:image/png;base64,iVBORw0KGgo..." } },
        { "type": "image_url", "image_url": { "url": "https://example.com/chart.png" } }
      ]
    }
  ]
}

Reasoning output

DeepSeek returns its thinking trace in a separate reasoning_content field, not inside content. Read it explicitly if you want it.

completion_tokens already includes reasoning tokens, so treat it as the real output length and do not add reasoning_tokens on top. This differs from Grok, where the chat endpoint reports them separately and they must be added.

Thinking draws from the same max_tokens budget as the answer, and it comes first. Set the budget too low and thinking consumes all of it; the call still returns 200, with this signature:

  • finish_reason is length.
  • content is an empty string.
  • completion_tokens_details.reasoning_tokens equals the budget you gave.

Read that combination as "raise max_tokens", not as a failed request. At max_tokens: 16 this model returns a truncated thought and no answer at all.

That budget rule holds for deepseek-v4.1-flash. On deepseek-v4-pro-202606 and deepseek-v4-flash-202605, max_tokens does not cap thinking while thinking is on: in tests, max_tokens: 64 returned 144–161 output tokens on Chat Completions and up to 1,299 on Anthropic Messages, all billed. With thinking turned off, the cap is exact.

The two ceilings do not behave alike. Input beyond the context window (1,048,576 tokens as measured) is rejected with a 400 before anything is generated, and nothing is billed. On Chat Completions, a max_tokens above the output ceiling is not rejected: the call returns 200 and the output is silently cut at the real ceiling, so a successful response is no proof that your budget was accepted.

Tool calling and prefix continuation

Tool calling

Standard OpenAI function calling works end to end: one call or several in parallel, tool_choice set to auto, none, required or a named function, and role: "tool" results fed back in.

This is a reasoning model and it still accepts required. Thinking stays on, and the reply comes back with finish_reason: "tool_calls".

Prefix continuation

Hand the model the opening of its own reply and it carries on from there: make the last entry of messages an assistant message and set prefix: true on it. The completion holds only the continuation; your text is not repeated.

In this mode the model produces no thinking trace: reasoning_content is absent, reasoning_tokens is 0, and the whole budget goes to the continuation.

{
  "model": "deepseek-v4.1-flash",
  "messages": [
    { "role": "user", "content": "List three primary colors, comma separated, nothing else." },
    { "role": "assistant", "content": "red, green,", "prefix": true }
  ]
}

The content that comes back for that request is blue, one output token.

Prompt caching and reconciliation

Prefix caching is implicit: there is nothing to switch on and no cache-control parameter to send. A hit is reported in the standard OpenAI field usage.prompt_tokens_details.cached_tokens. Hits need at least 256 tokens of shared prefix; below that cached_tokens stays 0.

Your HopBase usage record and the response body count input differently, which matters when you reconcile:

FieldMeaning
Response prompt_tokensWhole prompt, cached portion included
Usage record Input tokensPrompt minus the cached portion
Usage record Cached input tokensThe cached portion, listed separately

So the usage record's input plus cached input equals the response's prompt_tokens. Cache read is priced separately from plain input; see the signed-in model catalog for the rate that applies to your key.

Claude Code and Anthropic Messages

POST /v1/messages accepts standard Anthropic Messages requests for all three models and passes them to the model's own Anthropic-compatible interface, so Claude Code and the Anthropic SDK connect directly. For the SDK, set the base URL to https://api.hop-base.com, without /v1.

With CC Switch, open the key's ··· menu in the console, select Import CCS, then Claude Code. The import fills in the model; keep the default Anthropic format, with no local routing. To set it up by hand:

export ANTHROPIC_BASE_URL="https://api.hop-base.com"
export ANTHROPIC_AUTH_TOKEN="sk-your-key"
export ANTHROPIC_MODEL="deepseek-v4-pro-202606"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="deepseek-v4-flash-202605"
export CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000
claude

Claude Code does not know these IDs, so CLAUDE_CODE_MAX_CONTEXT_TOKENS tells it the real context window; without it, Claude Code compacts the conversation at 200K tokens. All three models are in the same group, so one key covers them all. More options are in Claude Code.

  • Thinking comes back in thinking blocks and counts toward output_tokens. thinking: {"type": "disabled"} turns it off.
  • A named tool in tool_choice ({"type": "tool", "name": …}) is called as asked. {"type": "any"} is ignored, and the model may answer in text.
  • Only deepseek-v4.1-flash reads images; an image sent to the other two returns 400, as described in Image input.
  • A max_tokens above the output ceiling is not rejected.
  • cache_control breakpoints are removed before the request goes out, so explicit caching is not available; automatic prefix caching still works. In tests on 2026-10-03, Claude Code read 94%–99% of the prompt from cache from the second turn on.

When you reconcile Anthropic Messages usage, input_tokens excludes the cached part and matches Input tokens in your usage record; cache_read_input_tokens matches Cached input tokens.

Gateway behavior

BehaviorEffect on your request
Empty messagesRejected with a 400 before the request goes out
Responses fields the model does not takeRemoved silently
Unsupported input[].type / tools[].typeNot removed — still a 400
  • The silently removed Responses fields include stream_options, truncation, user, reasoning.summary and text.verbosity.
  • Unsupported types include local_shell_call, file_search and code_interpreter.
  • The model field in the response always echoes the public ID you requested, so a client that asserts response.model == request.model keeps working.

Next steps