You can use DeepSeek with OpenRouter through a single OpenAI-compatible API endpoint. For the standard setup, you need an OpenRouter API key, not a DeepSeek API key. This guide shows you how to select a current DeepSeek model, send your first request with cURL, connect through the OpenAI Python SDK, control reasoning and provider routing, understand billing and privacy, and fix common errors. The working example uses the pinned OpenRouter slug deepseek/deepseek-v4.1-flash so the model version does not change unexpectedly.
Last reviewed: October 16, 2026.
Quick answer: create an OpenRouter API key, store it in the
OPENROUTER_API_KEYenvironment variable, send requests tohttps://openrouter.ai/api/v1/chat/completions, and use an OpenRouter DeepSeek slug such asdeepseek/deepseek-v4.1-flash. The generated answer is normally available atchoices[0].message.content.
What It Means to Use DeepSeek Through OpenRouter
OpenRouter sits between your application and one of the providers serving the selected DeepSeek model. Your application sends one standardized request to OpenRouter, and OpenRouter selects an eligible provider endpoint, handles authentication and billing, and returns a normalized response.
This changes four important parts of the integration:
- Credential: you authenticate with an OpenRouter API key.
- Base URL: you use
https://openrouter.ai/api/v1. - Model identifier: you use an OpenRouter slug such as
deepseek/deepseek-v4.1-flash, not the direct DeepSeek identifierdeepseek-flash. - Billing: requests use OpenRouter credits and any limit attached to the OpenRouter key.
You do not need a DeepSeek API key for a normal request funded with OpenRouter credits. A direct DeepSeek key becomes relevant only when you call DeepSeek directly or configure a supported bring-your-own-key arrangement.
Choose the Correct DeepSeek Model Slug
A model’s display name and its API slug are not interchangeable. Copy the slug from the OpenRouter DeepSeek model catalog rather than guessing it from the model name.
| OpenRouter model slug | Behavior | When to use it |
|---|---|---|
deepseek/deepseek-v4.1-flash | Pinned DeepSeek V4.1 Flash listing | Recommended for this tutorial, regression tests, and applications that need a predictable model target. |
~deepseek/deepseek-flash-latest | Automatically resolves to the latest eligible model in the DeepSeek Flash family | Useful when you want automatic model upgrades and can test changes after the alias moves. |
deepseek/deepseek-v4-pro-0813 | Pinned DeepSeek V4 Pro release | Suitable when you deliberately choose this Pro version and require reproducibility. |
~deepseek/deepseek-pro-latest | Automatically resolves to the latest eligible model in the DeepSeek Pro family | Useful when remaining on the latest Pro-family model matters more than pinning an exact version. |
The current Flash alias resolves to DeepSeek V4.1 Flash, while the current Pro alias resolves to DeepSeek V4 Pro 0813. An alias can move when OpenRouter promotes a newer family member, and its price, context, modalities, and supported parameters update with the resolved model. The response’s model field reports the concrete model that actually served an alias request.
Practical choice: start with deepseek/deepseek-v4.1-flash. Move to a latest alias only after your application logs the resolved model and can tolerate a version changing without a code deployment.
What You Need
- An OpenRouter account.
- An OpenRouter API key with a suitable spending limit.
- Enough OpenRouter credits for the selected paid model, unless you deliberately use an available free option.
- cURL for the first request, or Python with the OpenAI package for the SDK example.
- A non-sensitive test prompt.
Do not use a DeepSeek platform key in the OpenRouter Authorization header. OpenRouter and the direct DeepSeek API have separate credentials, balances, model identifiers, and billing systems.
Step 1: Create an OpenRouter API Key
- Sign in to OpenRouter.
- Open the OpenRouter API Keys page.
- Select the option to create a new key.
- Give it a descriptive name such as
deepseek-development. - Set a spending limit appropriate for your test or application.
- Copy the key when it appears and store it securely.
OpenRouter recommends setting a credit limit on each API key. A limited key reduces the damage caused by a leaked credential, a broken retry loop, or an agent that makes more calls than expected. Depending on the key configuration, limits can be lifetime, daily, weekly, or monthly.
Never expose the key in browser-side JavaScript, a public Git repository, a WordPress page, an application screenshot, or a downloadable code sample. Revoke and replace it immediately if it is exposed.
Step 2: Store the Key in an Environment Variable
For a temporary macOS or Linux shell session, run:
export OPENROUTER_API_KEY="sk-or-your-key-here"For a temporary Windows PowerShell session, run:
$env:OPENROUTER_API_KEY = "sk-or-your-key-here"These commands keep the key out of the request body, but they may remain in shell history. For production, use your hosting platform’s encrypted environment variables, an operating-system keychain, or a dedicated secrets manager.
Step 3: Send Your First DeepSeek Request with cURL
The following request uses the pinned DeepSeek V4.1 Flash slug and disables reasoning for a short, direct task:
curl https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek/deepseek-v4.1-flash",
"messages": [
{
"role": "system",
"content": "You are a concise technical assistant."
},
{
"role": "user",
"content": "Explain what an API gateway does in three bullet points."
}
],
"reasoning": {
"effort": "none"
},
"max_tokens": 300
}'The request contains four essential parts:
Authorizationsends the OpenRouter key as a Bearer token.modelidentifies the OpenRouter DeepSeek listing.messagescontains the conversation sent to the model.max_tokenslimits the combined completion budget.
The HTTP-Referer and X-OpenRouter-Title headers shown in some OpenRouter examples are optional app-attribution headers. They are not required for this minimal request. OpenRouter’s standard Chat Completions endpoint is /api/v1/chat/completions, and authentication uses a Bearer token.
Step 4: Verify the Response
A successful non-streaming response should contain a structure similar to this simplified example:
{
"id": "gen-...",
"model": "deepseek/deepseek-v4.1-flash",
"choices": [
{
"message": {
"role": "assistant",
"content": "..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}Inspect these fields:
choices[0].message.contentcontains the visible answer.modelidentifies the concrete model that handled the request.finish_reasonindicates whether the answer completed normally or stopped because of a limit or error.usagereports token usage used for monitoring and billing.
The zero values above are placeholders that show the response shape, not expected usage. Your actual response will contain real token counts.
When you send a latest alias, log the returned model value. That field tells you which concrete version answered the request and lets you detect an alias rollover.
Use DeepSeek with OpenRouter in Python
OpenRouter is compatible with the OpenAI SDK. Install the current Python package:
python -m pip install --upgrade openaiThen create a file such as deepseek_openrouter.py:
import os
import sys
from openai import APIStatusError, OpenAI
api_key = os.getenv("OPENROUTER_API_KEY")
if not api_key:
raise RuntimeError(
"OPENROUTER_API_KEY is not set. Add it to your environment first."
)
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=api_key,
)
try:
response = client.chat.completions.create(
model="deepseek/deepseek-v4.1-flash",
messages=[
{
"role": "system",
"content": "You are a concise technical assistant.",
},
{
"role": "user",
"content": "Explain what an API gateway does in three bullet points.",
},
],
max_tokens=300,
extra_body={
"reasoning": {
"effort": "none",
}
},
)
answer = response.choices[0].message.content
if not answer:
raise RuntimeError(
"The request succeeded but returned no visible answer."
)
print(answer)
print(f"\nModel used: {response.model}")
except APIStatusError as exc:
print(
f"OpenRouter returned HTTP {exc.status_code}: {exc.response.text}",
file=sys.stderr,
)
raiseThe important OpenRouter-specific change is the SDK’s base_url. The API key still comes from OPENROUTER_API_KEY, and OpenRouter-only request fields can be sent through extra_body. The answer remains available through response.choices[0].message.content.
Try DeepSeek in OpenRouter Without Code
You can test a model in the OpenRouter Chat Playground before creating an API integration:
- Open the OpenRouter Chat Playground.
- Open the model selector.
- Search for DeepSeek.
- Select a current model and verify whether its listing is paid or free.
- Send a non-sensitive test prompt.
- Review the model and provider information shown for the response.
The Playground is useful for comparing prompts and models, but an API request is still necessary when you want to connect DeepSeek to your own application, automation, or backend.
Control DeepSeek Reasoning Through OpenRouter
The current OpenRouter metadata for deepseek/deepseek-v4.1-flash reports optional reasoning with supported effort levels none, low, high, and max. Its current default is reasoning enabled at high effort. Setting the value explicitly makes your intended behavior clearer and protects the request from relying on an implicit default.
| Reasoning effort | Practical use |
|---|---|
none | Short summaries, classification, extraction, formatting, and other direct tasks. |
low | Tasks needing a small amount of planning without a large reasoning budget. |
high | More complex coding, analysis, and multi-step work. |
max | Difficult tasks where additional reasoning is justified by the expected latency and cost. |
For a complex task, the request fragment can use:
"reasoning": {
"effort": "high"
},
"provider": {
"require_parameters": true
}require_parameters restricts routing to provider endpoints that support the request’s parameters. That improves consistency but can reduce the number of eligible endpoints.
Reasoning tokens are billed as output tokens. On most providers, they also share the max_tokens budget with the visible answer. If the budget is too small, the model can consume it while reasoning and return empty or nearly empty visible content with finish_reason set to length. Increase the completion budget or reduce the reasoning effort when this happens.
Streaming, Tool Calls, and Structured Outputs
Streaming
Add "stream": true when your application should display the answer as it is generated. Streaming responses use Server-Sent Events, so your client must process multiple events rather than one final JSON object.
Do not rely only on the initial HTTP status. If generation fails after streaming begins, the connection can remain 200 OK while a later SSE event contains an error object and a choice with finish_reason: "error". Once part of an answer has reached the client, switching to another provider without duplicating or corrupting the output may no longer be possible.
Tool Calls and Structured JSON
The current OpenRouter listing for DeepSeek V4.1 Flash supports tools, tool_choice, and structured output through a JSON schema in response_format. However, feature support can still depend on the selected provider endpoint. Use provider.require_parameters: true when a workflow must not fall back to an endpoint that lacks a required parameter.
Always validate tool arguments and structured JSON before passing them to a database, shell command, payment action, or another external system. Model-generated data should not be treated as trusted application input.
How OpenRouter Provider Routing Works
OpenRouter can serve the same DeepSeek model through multiple upstream providers. Its default strategy considers provider stability, prioritizes lower-cost eligible endpoints, and keeps remaining providers available as fallbacks. You can override this behavior through the provider object.
| Goal | Provider setting | Trade-off |
|---|---|---|
| Use the default balanced route | Omit the provider object | OpenRouter chooses among eligible endpoints and retains fallback flexibility. |
| Prioritize the lowest price | "sort": "price" | Explicit sorting disables the normal load-balancing strategy. |
| Prioritize low latency | "sort": "latency" | The fastest observed endpoint may not be the cheapest. |
| Require parameter support | "require_parameters": true | Fewer endpoints may qualify. |
| Use only ZDR endpoints | "zdr": true | Privacy filtering may reduce availability. |
| Allow only selected providers | "only": ["provider-slug"] | Strongly limits failover and can leave no eligible endpoint. |
| Disable provider fallback | "allow_fallbacks": false | A problem at the selected endpoint is more likely to fail the request. |
A practical privacy-conscious configuration is:
"provider": {
"require_parameters": true,
"zdr": true,
"allow_fallbacks": true
}This allows fallback only among endpoints that satisfy the required parameters and OpenRouter’s ZDR classification. If no endpoint satisfies all restrictions, the request fails instead of silently ignoring them.
Avoid pinning one provider unless you have a documented reason such as a contractual data policy, regional requirement, specific performance profile, or provider-level compatibility issue. Overly restrictive routing removes much of OpenRouter’s availability advantage.
Can You Use DeepSeek on OpenRouter for Free?
OpenRouter provides two concepts that are often confused:
openrouter/freeselects a free model from the current free pool. It may select a DeepSeek model, but it does not guarantee DeepSeek for every request.- A model-specific
:freeslug selects a particular free listing, but only when that model has a separate free entry in the OpenRouter catalog.
Do not append :free to an arbitrary DeepSeek slug. Confirm that the exact free variant appears on the OpenRouter models page or in the Models API first.
Free-model availability changes, rate limits can be lower, latency can increase during busy periods, and a free endpoint may become temporarily unavailable. Free routes are useful for learning, light testing, and prototypes, but they should not be treated as guaranteed production capacity.
Privacy and API Key Security
A DeepSeek request sent through OpenRouter has at least two relevant data-handling layers: OpenRouter and the upstream provider endpoint that processes the inference. Their policies should not be treated as identical.
OpenRouter states that it does not store prompt or response content by default unless the account opts into input/output logging or allows OpenRouter to use that content. OpenRouter does retain request metadata such as model, token counts, and latency. Upstream providers have their own logging, retention, and training policies.
OpenRouter’s Zero Data Retention control restricts inference routing to endpoints classified as retaining no request data. It can be enforced in account settings or per request with provider.zdr: true. ZDR applies to inference routing; it does not automatically cover optional plugins and tools such as web search, which may use separate third-party services.
- Test with non-sensitive sample data.
- Send only the fields required for the task.
- Keep the API key on the server side.
- Set a spending limit and monitor key usage.
- Review OpenRouter privacy settings and eligible provider policies.
- Do not assume that ZDR alone satisfies every legal or regulatory obligation.
- Review the data path of any web search, file-processing, or external tool added to the request.
How OpenRouter Billing Differs from DeepSeek Billing
OpenRouter requests consume OpenRouter credits. A balance or promotion on the direct DeepSeek platform does not fund an OpenRouter request, and an OpenRouter credit balance does not fund a direct call to api.deepseek.com.
Do not copy a token price from an old tutorial. OpenRouter can expose several provider endpoints for the same model, and those endpoints may have different input, output, cache, or promotional rates. Latest aliases also have no permanently fixed price of their own because they inherit the pricing of the concrete model to which they currently resolve.
- Check the current OpenRouter model page before estimating costs.
- Review the available provider endpoints and their rates.
- Set a limit on each application key.
- Log model, provider, token usage, and cost for production requests.
- Remember that reasoning tokens count as output usage.
OpenRouter vs the Direct DeepSeek API
| Area | DeepSeek through OpenRouter | Direct DeepSeek API |
|---|---|---|
| Credential | OpenRouter API key | DeepSeek API key |
| Base URL | https://openrouter.ai/api/v1 | https://api.deepseek.com |
| Example current model ID | deepseek/deepseek-v4.1-flash | deepseek-flash |
| Billing | OpenRouter credits and key limits | Direct DeepSeek account balance |
| Provider choice | Can route across multiple eligible providers | DeepSeek’s own API service |
| Fallback | Can retry other eligible providers for the same model | Managed within the direct DeepSeek service rather than across OpenRouter providers |
| Other model families | Available through the same OpenRouter key and API format | Limited to models and services offered by DeepSeek |
| Privacy controls | OpenRouter settings plus upstream provider policies | DeepSeek’s direct API policies |
| Best fit | Unified multi-model applications, provider routing, fallback, and centralized usage controls | Applications that want a direct DeepSeek relationship, direct billing, and DeepSeek-native service behavior |
DeepSeek’s current direct API documentation lists deepseek-flash for DeepSeek V4.1 Flash and deepseek-v4-pro for DeepSeek V4 Pro. Those are direct DeepSeek identifiers and should not replace the OpenRouter slugs in this guide.
Neither route is automatically cheaper, faster, more private, or more reliable in every situation. Compare the exact model version, endpoint, current rates, routing requirements, and data policy relevant to your application.
Common DeepSeek and OpenRouter Errors
| Symptom or status | Likely cause | What to do |
|---|---|---|
400 Bad Request | Malformed JSON, missing messages, invalid role, or an unsupported parameter value | Validate the request body and compare every field with the current Chat Completions and model documentation. |
401 Unauthorized | The OpenRouter key is missing, invalid, disabled, expired, or sent without the Bearer prefix | Confirm that OPENROUTER_API_KEY contains an active OpenRouter key and that the header uses Authorization: Bearer .... |
402 Payment Required | The account or key has insufficient OpenRouter credits | Check the OpenRouter balance and confirm that you are not expecting a direct DeepSeek balance to fund the request. |
403 Forbidden | A key, workspace, or guardrail budget was reached, permissions are insufficient, or a guardrail blocked the request | Inspect error.metadata, the key limit, workspace budget, guardrails, and any reset time. |
404 Not Found | The model slug is wrong or account and request-level provider restrictions leave no matching provider | Copy the model slug from the current catalog and relax conflicting provider restrictions. |
408 Request Timeout | The request exceeded the allowed processing time | Reduce unnecessary context, review reasoning effort, and retry cautiously when the task is safe to repeat. |
429 Too Many Requests | An OpenRouter or upstream provider rate limit was reached | Honor the Retry-After header when present and use exponential backoff rather than an immediate retry loop. |
502 provider error | The selected model endpoint was unavailable or returned an invalid response | Keep fallbacks enabled, check OpenRouter status, and retry after a short delay. |
503 or “no available provider” | No endpoint meets the model, parameter, privacy, regional, price, or provider filters | Remove unnecessary only, ZDR, region, price, or parameter restrictions, or select another current model. |
200 OK with an error body | The provider began processing and then failed | Inspect the body for error even when the HTTP status is 200. |
| Streaming begins and then stops with an error event | A mid-stream provider failure, timeout, capacity problem, filter, or token limit occurred | Handle SSE error events and check for finish_reason: "error". |
Empty visible answer with finish_reason: "length" | Reasoning consumed most or all of the completion budget | Increase max_tokens or reduce reasoning.effort. |
| An alias produces different behavior after previously working | The latest alias resolved to a newer concrete model | Read the returned model field and switch to a pinned slug when reproducibility is required. |
OpenRouter normalizes provider failures through an error_type field. For Chat Completions, it can appear at error.metadata.error_type. This is more useful for application logic than relying only on the HTTP status because several upstream failures can share a status code.
Do not retry authentication failures, malformed requests, or exhausted key limits indefinitely. Retry only transient failures, respect Retry-After when supplied, and cap the number of attempts.
Production Checklist
- Use a separate OpenRouter key for each application or environment.
- Apply a spending limit to every key.
- Use a pinned model slug when reproducible behavior matters.
- Log the concrete model returned by latest aliases.
- Store secrets in a server-side secret manager.
- Validate model-generated JSON and tool arguments.
- Set reasoning effort deliberately rather than relying on a default.
- Use
require_parameterswhen a feature is mandatory. - Keep provider fallbacks enabled unless a verified requirement prevents them.
- Handle non-streaming and mid-stream error bodies.
- Use bounded retries with backoff.
- Monitor token usage, cost, model, provider, latency, and failure rates.
- Review OpenRouter and upstream provider data policies before sending sensitive information.
Frequently Asked Questions
Do I need a DeepSeek API key to use DeepSeek on OpenRouter?
No. Standard OpenRouter requests use an OpenRouter API key and OpenRouter credits. A DeepSeek API key is used for the direct DeepSeek platform, not as the Bearer credential for the OpenRouter endpoint.
What is the OpenRouter base URL for DeepSeek?
Use https://openrouter.ai/api/v1 as the SDK base URL. For a raw Chat Completions request, send the POST request to https://openrouter.ai/api/v1/chat/completions.
Which DeepSeek model should I use on OpenRouter?
For a current general-purpose starting point, use the pinned slug deepseek/deepseek-v4.1-flash. Use ~deepseek/deepseek-flash-latest when you prefer automatic Flash-family upgrades and can tolerate the model changing. Use a Pro-family listing only when the task justifies that choice.
Can I use the OpenAI SDK with DeepSeek on OpenRouter?
Yes. Point the OpenAI SDK to https://openrouter.ai/api/v1, authenticate with the OpenRouter key, and use an OpenRouter DeepSeek model slug. OpenRouter-specific options can be sent through the SDK’s extra-body mechanism.
Does OpenRouter always send DeepSeek requests to DeepSeek itself?
No. OpenRouter can route the selected model through multiple eligible providers. You can inspect provider information in OpenRouter logs or restrict routing, but strict provider filters reduce fallback options.
Is DeepSeek free through OpenRouter?
Some free OpenRouter routes may include DeepSeek models, but availability is not permanent or guaranteed. The openrouter/free router chooses from the current free pool and may select a different model. A specific :free slug works only when OpenRouter lists that model as a separate free variant.
Are prompts stored when I use DeepSeek through OpenRouter?
OpenRouter states that prompt and response content is not stored by default unless you opt into relevant logging or data-use settings, although request metadata is retained. The upstream provider has its own policy. Use OpenRouter’s provider policy controls or ZDR routing when required, and separately review any plugins or tools added to the request.
Why does OpenRouter say no endpoints are available?
The selected model may be unavailable, or your provider, privacy, region, parameter, quantization, latency, or price filters may exclude every endpoint. Remove nonessential restrictions one at a time, confirm the model slug, and review the current endpoint list.
Final Takeaway
The most reliable way to start using DeepSeek with OpenRouter is to create a limited OpenRouter API key, store it in OPENROUTER_API_KEY, send requests to the OpenRouter Chat Completions endpoint, and begin with a pinned slug such as deepseek/deepseek-v4.1-flash.
After the first request succeeds, choose reasoning effort deliberately, log the concrete model and usage, and add provider restrictions only when they solve a documented requirement. Use latest aliases for automatic upgrades, pinned slugs for reproducibility, ZDR for eligible no-retention routing, and bounded retries for temporary provider or rate-limit failures.
Official Documentation Checked
- OpenRouter Quickstart
- OpenRouter API authentication
- OpenRouter DeepSeek model catalog
- DeepSeek V4.1 Flash on OpenRouter
- OpenRouter latest-model aliases
- OpenRouter provider routing
- OpenRouter reasoning controls
- OpenRouter errors and debugging
- OpenRouter data collection
- OpenRouter Zero Data Retention
- Direct DeepSeek models and pricing
