Loading page
Please wait while the page loads.
Please wait while the page loads.
Developers / API reference
From authentication to project-context injection, model routing and streaming: everything a request goes through inside DeepCodex, in one place.
https://www.deepcodex.cn/v1| Protocol | Method | URL | Status | Streaming | Typical use |
|---|---|---|---|---|---|
| OpenAI Chat Completions | POST | https://www.deepcodex.cn/v1/chat/completions | Supported | Streams | SDKs / curl / most terminals |
| OpenAI Responses | POST | https://www.deepcodex.cn/v1/responses | Supported | Streams | Codex CLI |
| Anthropic Messages | POST | https://www.deepcodex.cn/v1/messages | Beta | Streams | Claude Code |
| Anthropic Messages | POST | https://www.deepcodex.cn/v1/messages/count_tokens | Beta | No stream | Claude Code |
| OpenAI Completions (FIM) | POST | https://www.deepcodex.cn/v1/completions | Supported | Streams | Completion / FIM |
| Model list | GET | https://www.deepcodex.cn/v1/models | Supported | No stream | Model discovery by terminals |
| Plan | OpenAI Chat | Anthropic Messages | OpenAI Responses |
|---|---|---|---|
| 免费版 | Supported | Not included | Not included |
| 入门版 | Supported | Not included | Not included |
| 专业版 | Supported | Not included | Not included |
| Pro Plus | Supported | Supported | Supported |
| Pro Max | Supported | Supported | Supported |
Base URL
https://www.deepcodex.cn/v1Authorization: Bearer dck_live_8f2a••••
X-DeepCodex-Project: payments-api
Content-Type: application/json| Model | Context | Max output | Best for | Notes | Ratio |
|---|---|---|---|---|---|
deepseek-flashDeepSeek Flash | 1M | 384K | Quick rewrites, retrieval, batches of small tasks | Vision · Thinking · Aliases: deepseek-v4-flash | 1× |
deepseek-v4-proDeepSeek V4 Pro | 1M | 384K | Long reasoning chains with visible thinking | Thinking | 4× |
curl https://www.deepcodex.cn/v1/chat/completions \
-H "Authorization: Bearer $DEEPCODEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-flash","stream":true,"messages":[{"role":"user","content":"Make the order callback idempotent"}]}'Config location: ~/.codex/config.toml
# ~/.codex/config.toml
model = "deepseek-v4-pro"
model_provider = "deepcodex"
[model_providers.deepcodex]
name = "deepcodex"
base_url = "https://www.deepcodex.cn/v1"
env_key = "DEEPCODEX_API_KEY"
wire_api = "responses"export DEEPCODEX_API_KEY=dck_xxx
codexSend a short message to check the connection. For a 403 response, check that your plan includes the required protocol. Keep keys out of source control.
| Dimension | Meaning | Notes |
|---|---|---|
| Concurrency | Requests in flight at once | Per plan; burst concurrency is counted separately |
| RPM | Requests per minute | Can be tightened per key |
| QPS | Requests per second | Per account; plans without a ceiling take the platform default, and each key can tighten it |
| Period cap | Equivalent tokens per billing period | An in-app / email alert fires at 80% |
Response headers
Retry-AfterX-DeepCodex-RPM-Limit / -Remaining / -ResetX-DeepCodex-QPS-Limit / -Remaining / -ResetX-DeepCodex-Quota-RemainingX-DeepCodex-Quota-ResetMatching reason_code
concurrency_exceededrpm_exceededquota_exceededqps_exceededkey_qps_exceeded| Category | reason_code | HTTP | Meaning | What to do |
|---|---|---|---|---|
| Authentication | invalid_api_key | 401 | The key is unknown or malformed | Regenerate the key on the API Keys page and update the terminal config |
| Authentication | api_key_revoked | 401 | The key was revoked | The key was revoked; create a new one on the API Keys page |
| Authentication | api_key_expired | 401 | The key has passed its expiry date | The key passed its expiry; create a new one on the API Keys page |
| Authentication | key_disabled | 401 | The key is disabled; enable it on the keys page | Re-enable the key on the API Keys page or use another key |
| Authentication | user_disabled | 403 | The account is disabled | The account is disabled; contact support |
| Authentication | ip_not_allowed | 403 | The caller's IP is outside the key's allow-list | Add the caller IP to the key's IP allowlist |
| Authentication | identity_required | 403 | Identity verification is required before calling | Finish identity verification in Settings before calling the API |
| Plan | no_active_subscription | 403 | No active plan | Subscribe to a plan on the plan page |
| Plan | subscription_expired | 403 | The plan period has ended | Renew the plan on the plan page |
| Plan | model_not_allowed_by_key | 403 | The key's model allow-list excludes this model | Relax the model restriction in the key detail |
| Plan | model_not_allowed_by_plan | 403 | The plan does not include this model | Pick a model included in the plan or upgrade |
| Plan | protocol_not_in_plan | 403 | The plan does not include this protocol | Use a protocol included in the plan or upgrade |
| Plan | capability_unavailable | 403 | This request needs image or hosted-tool capability the plan cannot fund | This request carries an image or a provider-executed tool; upgrade to a plan with an assist allowance, or send it without the image or tool |
| Request | model_required | 400 | The request has no model | Set the model field in the request body |
| Request | model_not_found | 404 | Unknown model code | Use a model code from GET /v1/models |
| Request | unsupported_model_protocol | 400 | This model cannot be called through this protocol | Call the model through the protocol listed in the model catalog |
| Request | invalid_request_error | 400 | The request body failed validation | Fix the request body as described in the error message |
| Request | invalid_json | 400 | The body is not valid JSON | Send a valid JSON body with Content-Type: application/json |
| Request | body_unreadable | 400 | The body could not be read | Resend the request; check the client's connection and proxy |
| Request | body_too_large | 413 | The body exceeds the size limit | Shorten the prompt or split the request |
| Request | invalid_project_id | 400 | The project header is not a valid id | Pass an existing project id from the projects page |
| Request | project_limit_reached | 400 | Too many projects on this account | Delete an unused project or upgrade the plan |
| Quota | quota_exceeded | 429 | Equivalent-token quota for the period is used up; the response carries the reset time | Top up, upgrade the plan or wait for the period reset named by X-DeepCodex-Quota-Reset. A Codex thread goal shows this as usage_limited and stops continuing; resume it with /goal resume once the allowance is back |
| Quota | key_quota_exceeded | 429 | This key's token cap for the period is used up | Raise the key's quota in the key detail or use another key. A Codex thread goal shows this as usage_limited; resume it with /goal resume after raising the cap |
| Quota | provider_quota_exceeded | 429 | The plan's allowance for this provider is used up | Wait for the provider window to reset or switch model. A Codex thread goal shows this as usage_limited; resume it with /goal resume once the window is back |
| Quota | assist_quota_exceeded | 429 | The assistant's share of the allowance is used up | Wait for the assistant quota to reset or upgrade. A Codex thread goal shows this as usage_limited; resume it with /goal resume once the quota is back |
| Quota | rpm_exceeded | 429 | Above the per-minute request limit | Back off and retry per Retry-After; X-DeepCodex-RPM-Limit/-Remaining/-Reset show the window |
| Quota | key_rpm_exceeded | 429 | This API key's own per-minute ceiling is full | This API key has its own per-minute ceiling; raise it in the key detail or spread the load over more keys |
| Quota | qps_exceeded | 429 | Above the per-second request limit | Spread requests out and retry per Retry-After (1s); X-DeepCodex-QPS-Limit/-Remaining/-Reset show the window |
| Quota | key_qps_exceeded | 429 | This API key's own per-second ceiling is full | This API key has its own per-second ceiling; raise it in the key detail or spread the load over more keys |
| Quota | concurrency_exceeded | 429 | Above the key, account or platform concurrency limit | Lower concurrency or upgrade; retry per Retry-After (2s). A slot frees when an in-flight call finishes, so there is no window to wait out |
| Quota | platform_concurrency_exceeded | 429 | The platform is at capacity for this model; retry shortly | Retry with backoff; the platform is at capacity |
| Upstream | upstream_rate_limited | 429 | The upstream provider throttled the call; retry shortly | Retry with backoff; another credential is tried automatically |
| Upstream | upstream_rejected_request | 400 | The upstream provider rejected the request; its message is passed through | Check the request parameters against the model's limits |
| Upstream | upstream_error | 502 | The upstream provider returned an error | Retry; the reason is in the request detail |
| Upstream | upstream_auth_failed | 502 | The platform credential was refused upstream | Retry; the operator is notified about the credential |
| Upstream | upstream_unreachable | 502 | The upstream provider could not be reached | Retry; another credential is tried automatically |
| Upstream | upstream_timeout | 504 | The upstream provider did not answer in time | Shorten the output or retry |
| Upstream | upstream_stream_broken | 502 | The stream ended early | Retry the request; partial output is not billed twice |
| Upstream | upstream_response_invalid | 502 | The upstream answer could not be parsed | Retry; the reason is in the request detail |
| Upstream | upstream_request_invalid | 502 | The translated request was refused upstream | Check the request parameters; contact support if it persists |
| Platform | no_upstream_available | 503 | No healthy upstream for this model right now | Retry shortly or pick another model |
| Platform | auth_unavailable | 503 | Key lookup is temporarily unavailable | Retry shortly; contact support if it persists |
| Platform | identity_unavailable | 503 | Identity lookup is temporarily unavailable | Retry shortly; contact support if it persists |
| Platform | admission_unavailable | 503 | Quota accounting is temporarily unavailable | Retry shortly; contact support if it persists |
| Platform | model_catalog_unavailable | 503 | The model catalog is temporarily unavailable | Retry shortly; contact support if it persists |
| Platform | upstream_catalog_unavailable | 503 | The upstream catalog is temporarily unavailable | Retry shortly; contact support if it persists |
| Request | image_invalid | 400 | Request | Check the prompt length, size and image format |
| Request | image_too_large | 413 | Request | Upload a smaller image (see image_max_bytes) |
| Plan | images_not_in_plan | 403 | Plan | Upgrade to a plan that includes the image workbench |
| Platform | images_unconfigured | 503 | Platform | Image generation is not configured yet; contact support |
| Upstream | upstream_failed | 502 | Upstream | Retry; the reason is in the request detail |
| Platform | not_supported | 501 | Platform | Update the assistant to a newer version |
| Request | invalid_memory_kind | 400 | Request | Use one of fact, pitfall, decision, preference or structure |
| Request | saved_search_empty | 400 | Request | Enter a keyword before saving the search condition |
| Request | saved_search_limit | 409 | Request | Delete a saved condition before adding another |
| Request | saved_search_duplicate | 409 | Request | This condition is already saved; open it from the list |
Where to configure
Console → Settings → Webhooks: enter a public https endpoint, pick the events, and copy the signing secret — it is shown once. Up to 10 endpoints per account; each can be disabled, have its secret rotated, or be sent a test event. Delivery records are kept for 30 days.
Webhooks are a Pro Plus (and above) capability; without it the settings tab shows an upgrade notice.
Request body
Every delivery is a POST with Content-Type application/json. The envelope is always id / type / occurred_at / data; the shape of data depends on the event type.
{
"id": "agent_run.completed:0f2c…:succeeded",
"type": "agent_run.completed",
"occurred_at": "2026-09-17T08:30:11Z",
"data": { "run_id": "0f2c…", "status": "succeeded", "tokens": 18422 }
}| Event | Fires when | Main data fields |
|---|---|---|
agent_run.completed | A cloud agent run finishes (succeeded or failed) | run_id, status, summary, tokens, cost_cny_cents, compute_seconds, engine, caller, repo, branch, mode, created_at, finished_at; plus project_id, task_id, tests_passed when known |
task.summarized | A conversation is digested into a task summary and cards | task_id, project_id, summary, intent_level, request_count, equiv_tokens, cards[], started_at, ended_at |
workflow_run.completed | A workflow run finishes | workflow_run_id, workflow_id, workflow_name, status, repo, branch, steps_completed, tokens, cost_cny_cents, created_at, finished_at |
usage_threshold | This period's usage crosses an alert threshold | title, message, notified_at, threshold_percent, usage_percent, used_equiv_tokens, total_equiv_tokens, period_end, plan_code |
The set is closed: an unknown type in a subscription is not an error but never fires. Subscribing to nothing means every event. Payloads are built field by field from an allowlist and never name a model or an upstream provider.
Request headers
X-Deepcodex-EventX-Deepcodex-Event-IdX-Deepcodex-DeliveryX-Deepcodex-AttemptX-Deepcodex-TimestampX-Deepcodex-SignatureNode.js example
import crypto from "node:crypto";
// X-Deepcodex-Signature: t=<unix seconds>,v1=<hex hmac>
export function verifyDeepcodexWebhook(rawBody, signature, secret) {
const parts = Object.fromEntries(signature.split(",").map((part) => part.split("=")));
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
const given = Buffer.from(parts.v1 ?? "", "hex");
const want = Buffer.from(expected, "hex");
if (given.length !== want.length || !crypto.timingSafeEqual(given, want)) return false;
// Reject a timestamp more than five minutes out to stop replays.
return Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
}| Rule | Detail |
|---|---|
| Success | Any 2xx counts as delivered. The request times out after 10 seconds and 3xx redirects are not followed, so a signed payload never reaches an address you did not register |
| Backoff | After a failure: 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours — five attempts, spanning roughly eight hours |
| At least once | Delivery is at-least-once: key your handler on X-Deepcodex-Event-Id and ignore an id you have already processed |
| When it stops | Disabling or deleting an endpoint voids its queued deliveries; an event that fails five times is not retried again, and the delivery record keeps the last response code and error |
| Endpoint rules | A public https URL, without credentials in it, and never a loopback, private or link-local address |