How to Use DeepSeek with OpenRouter: API Setup, Models, and Troubleshooting

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_KEY environment variable, send requests to https://openrouter.ai/api/v1/chat/completions, and use an OpenRouter DeepSeek slug such as deepseek/deepseek-v4.1-flash. The generated answer is normally available at choices[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 identifier deepseek-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 slugBehaviorWhen to use it
deepseek/deepseek-v4.1-flashPinned DeepSeek V4.1 Flash listingRecommended for this tutorial, regression tests, and applications that need a predictable model target.
~deepseek/deepseek-flash-latestAutomatically resolves to the latest eligible model in the DeepSeek Flash familyUseful when you want automatic model upgrades and can test changes after the alias moves.
deepseek/deepseek-v4-pro-0813Pinned DeepSeek V4 Pro releaseSuitable when you deliberately choose this Pro version and require reproducibility.
~deepseek/deepseek-pro-latestAutomatically resolves to the latest eligible model in the DeepSeek Pro familyUseful 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

  1. Sign in to OpenRouter.
  2. Open the OpenRouter API Keys page.
  3. Select the option to create a new key.
  4. Give it a descriptive name such as deepseek-development.
  5. Set a spending limit appropriate for your test or application.
  6. 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:

  • Authorization sends the OpenRouter key as a Bearer token.
  • model identifies the OpenRouter DeepSeek listing.
  • messages contains the conversation sent to the model.
  • max_tokens limits 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.content contains the visible answer.
  • model identifies the concrete model that handled the request.
  • finish_reason indicates whether the answer completed normally or stopped because of a limit or error.
  • usage reports 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 openai

Then 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,
    )
    raise

The 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:

  1. Open the OpenRouter Chat Playground.
  2. Open the model selector.
  3. Search for DeepSeek.
  4. Select a current model and verify whether its listing is paid or free.
  5. Send a non-sensitive test prompt.
  6. 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 effortPractical use
noneShort summaries, classification, extraction, formatting, and other direct tasks.
lowTasks needing a small amount of planning without a large reasoning budget.
highMore complex coding, analysis, and multi-step work.
maxDifficult 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.

GoalProvider settingTrade-off
Use the default balanced routeOmit the provider objectOpenRouter 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": trueFewer endpoints may qualify.
Use only ZDR endpoints"zdr": truePrivacy 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": falseA 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/free selects 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 :free slug 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

AreaDeepSeek through OpenRouterDirect DeepSeek API
CredentialOpenRouter API keyDeepSeek API key
Base URLhttps://openrouter.ai/api/v1https://api.deepseek.com
Example current model IDdeepseek/deepseek-v4.1-flashdeepseek-flash
BillingOpenRouter credits and key limitsDirect DeepSeek account balance
Provider choiceCan route across multiple eligible providersDeepSeek’s own API service
FallbackCan retry other eligible providers for the same modelManaged within the direct DeepSeek service rather than across OpenRouter providers
Other model familiesAvailable through the same OpenRouter key and API formatLimited to models and services offered by DeepSeek
Privacy controlsOpenRouter settings plus upstream provider policiesDeepSeek’s direct API policies
Best fitUnified multi-model applications, provider routing, fallback, and centralized usage controlsApplications 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 statusLikely causeWhat to do
400 Bad RequestMalformed JSON, missing messages, invalid role, or an unsupported parameter valueValidate the request body and compare every field with the current Chat Completions and model documentation.
401 UnauthorizedThe OpenRouter key is missing, invalid, disabled, expired, or sent without the Bearer prefixConfirm that OPENROUTER_API_KEY contains an active OpenRouter key and that the header uses Authorization: Bearer ....
402 Payment RequiredThe account or key has insufficient OpenRouter creditsCheck the OpenRouter balance and confirm that you are not expecting a direct DeepSeek balance to fund the request.
403 ForbiddenA key, workspace, or guardrail budget was reached, permissions are insufficient, or a guardrail blocked the requestInspect error.metadata, the key limit, workspace budget, guardrails, and any reset time.
404 Not FoundThe model slug is wrong or account and request-level provider restrictions leave no matching providerCopy the model slug from the current catalog and relax conflicting provider restrictions.
408 Request TimeoutThe request exceeded the allowed processing timeReduce unnecessary context, review reasoning effort, and retry cautiously when the task is safe to repeat.
429 Too Many RequestsAn OpenRouter or upstream provider rate limit was reachedHonor the Retry-After header when present and use exponential backoff rather than an immediate retry loop.
502 provider errorThe selected model endpoint was unavailable or returned an invalid responseKeep 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 filtersRemove unnecessary only, ZDR, region, price, or parameter restrictions, or select another current model.
200 OK with an error bodyThe provider began processing and then failedInspect the body for error even when the HTTP status is 200.
Streaming begins and then stops with an error eventA mid-stream provider failure, timeout, capacity problem, filter, or token limit occurredHandle SSE error events and check for finish_reason: "error".
Empty visible answer with finish_reason: "length"Reasoning consumed most or all of the completion budgetIncrease max_tokens or reduce reasoning.effort.
An alias produces different behavior after previously workingThe latest alias resolved to a newer concrete modelRead 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_parameters when 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