The current documented DeepSeek API model IDs are deepseek-v4-flash and deepseek-v4-pro. In our bounded live snapshot on July 25, 2026, GET /models returned HTTP 200 and exactly those two IDs. Minimal requests to both current IDs returned HTTP 200 and the exact requested marker. Requests using deepseek-chat, deepseek-reasoner, and the historical deepseek-coder name each returned HTTP 400, as did one deliberately invalid control.
That runtime result is useful, but it does not define lifecycle policy. DeepSeek’s dated V4 announcement and change log establish the official retirement of deepseek-chat and deepseek-reasoner; our calls establish only that the exact identifiers were rejected for the tested account, endpoint, payload, and UTC window. deepseek-coder was tested because it appears in DeepSeek’s own historical change log, but its HTTP 400 is an observed rejection, not a newly invented deprecation notice.
This tracker keeps those evidence classes separate. It combines first-party lifecycle notices, a dated model inventory, bounded compatibility probes, and an operational migration runbook. Chat-Deep.ai is an independent technical site and is not affiliated with DeepSeek.
Status at a glance
- Current documented and observed working:
deepseek-v4-flash,deepseek-v4-pro - Officially retired legacy aliases:
deepseek-chat,deepseek-reasoner - Observed on July 25, 2026: both retired aliases returned HTTP 400
- Historical name tested:
deepseek-coderreturned HTTP 400 - Invalid control:
deepseek-invalid-control-a30returned HTTP 400 - Evidence budget: seven planned calls, seven observed calls, zero automatic retries
Freshness and test disclosure
| Evidence item | Value |
|---|---|
| Official documentation reviewed | July 25, 2026 |
| Live API test window | 2026-07-25 23:42:14.910Z to 23:42:18.512Z |
| Tracker last updated | July 25, 2026 |
| Planned and observed calls | 7 of 7 |
| Credential handling | Dedicated temporary key; revocation verified after the run |
| Test content | Synthetic English markers only |
The temporary key was never written to the article package. Raw request and response bodies, provider error messages, response headers, completion IDs, generated non-fixture output, and raw system_fingerprint values were not retained. The published evidence shows only allowlisted fields needed to support the findings.
On this page
- Current DeepSeek API status
- How the tracker classifies evidence
- Current model inventory
- Live compatibility test
- DeepSeek API update timeline
- Lifecycle terms that must not be mixed
- Migration playbook
- Contract-test code
- Update cadence
- Limitations
- Frequently asked questions
Current DeepSeek API status
DeepSeek’s current Models and Pricing page, model-list reference, and Chat Completion reference identify two first-class model IDs:
| Exact API ID | Current documented role | Live /models result | Minimal chat result | Bounded verdict |
|---|---|---|---|---|
deepseek-v4-flash | Lower-cost V4 option | Listed | HTTP 200; exact marker | Documented current and observed accepted |
deepseek-v4-pro | Higher-capability V4 option | Listed | HTTP 200; exact marker | Documented current and observed accepted |
deepseek-chat | Retired legacy alias | Not listed | HTTP 400 | Officially retired; observed rejected |
deepseek-reasoner | Retired legacy alias | Not listed | HTTP 400 | Officially retired; observed rejected |
deepseek-coder | Historical API name | Not listed | HTTP 400 | Historical name; observed rejected |
deepseek-invalid-control-a30 | Synthetic invalid control | Not listed | HTTP 400 | Intentionally invalid; observed rejected |
The DeepSeek V4 release notice announced that the legacy aliases would be fully retired and inaccessible after July 24, 2026 at 15:59 UTC. The official change log describes them as discontinued after that deadline. Our test ran the next day. This sequencing matters: the official sources support the retirement label, while the subsequent test records the response actually observed.
The test does not imply that every account, region, SDK path, or future date will produce the same response. It also does not turn every HTTP 400 into a model-retirement signal. A malformed payload can return the same status. The invalid control was included specifically to show that status alone does not explain lifecycle.
How this tracker decides whether a model is deprecated
The word “deprecated” is reserved for explicit first-party lifecycle language. A model missing from a list, a failed request, a changed fingerprint, or a community report cannot independently establish an official deprecation.

We use the following evidence order:
- Dated first-party lifecycle notice. A release note, change log, or reference explicitly says deprecated, discontinued, retired, removed, or unavailable after a stated date.
- Authenticated inventory observation.
GET /modelsshows which IDs were exposed to the tested account at a precise time. - Minimal request observation. A controlled request records acceptance or rejection of an exact identifier.
- Current reference and pricing surfaces. These show currently documented request enums, capabilities, and commercial entries.
- Historical first-party records. These establish that an old identifier existed and how it was described then.
- Editorial inference. Any conclusion that goes beyond the evidence is labeled as a hypothesis, not product policy.
This hierarchy answers different questions. An official notice explains provider intent and effective dates. A model-list response reports inventory. A request reports one runtime outcome. The tracker does not collapse them into a single “works/does not work” badge.
The three labels used in every update
Documented status records exactly what DeepSeek says and the date on which it takes effect. Observed status records what the tested API path returned in a fixed UTC window. Migration action tells an operator what to verify next. A change is not closed until all three fields are updated.
That structure also handles documentation lag. At the time of review, some introductory or pricing text still displayed legacy aliases with deprecation notes, while the current model-list example and Chat Completion enum showed only the V4 IDs. The dated retirement notice remains the lifecycle source; a stale mention elsewhere does not resurrect an alias.
Current documented model IDs and live /models results
The documented operation is:
curl https://api.deepseek.com/models \
-H "Authorization: Bearer $DEEPSEEK_API_KEY"
Never publish the real Authorization value or paste an account response into a public issue without sanitizing it. For an automated tracker, retain exact known model IDs, count unexpected rows, and hash the sanitized snapshot. Do not retain unrelated account metadata.

Our July 25 response passed the documented list shape and contained exactly two entries:
{
"observed_http": 200,
"contract_valid": true,
"model_ids": [
"deepseek-v4-flash",
"deepseek-v4-pro"
],
"unexpected_entry_count": 0,
"checked_utc": "2026-07-25T23:42:15Z"
}
This is a privacy-safe reconstruction from allowlisted evidence, not the raw provider response. Neither retired alias nor the historical coder name appeared. Absence means “not listed in this response.” For deepseek-chat and deepseek-reasoner, the separate official retirement notice supplies the lifecycle verdict. For deepseek-coder, absence plus an HTTP 400 remains a dated runtime observation.
Current prices used for the tiny test estimate
The pricing page reviewed on July 25 listed cache-hit input, cache-miss input, and output rates per million tokens. The successful marker calls used 43 uncached prompt tokens and nine completion tokens, or 52 total tokens. Applying those dated list rates produced a derived estimate of $0.000017095:
| Model | Prompt tokens | Completion tokens | Derived call cost |
|---|---|---|---|
deepseek-v4-flash | 22 | 5 | $0.000004480 |
deepseek-v4-pro | 21 | 4 | $0.000012615 |
| Total | 43 | 9 | $0.000017095 |
This number is a usage-derived calculation, not an invoice, balance lookup, or guarantee of future pricing. Always check the live DeepSeek pricing table before budgeting.
What the controlled live test measured
The candidate set and seven-call ceiling were fixed before execution. Calls were sequential, automatic retries were disabled, and each successful completion had to return its exact synthetic marker. The marker check prevents a superficially successful response from being counted when the body did not satisfy the tiny contract.
| Order | Operation or exact ID | HTTP | Sanitized result |
|---|---|---|---|
| 1 | GET /models | 200 | Valid list; exactly Flash and Pro |
| 2 | deepseek-v4-flash | 200 | Returned model matched; exact marker |
| 3 | deepseek-v4-pro | 200 | Returned model matched; exact marker |
| 4 | deepseek-chat | 400 | Rejected; raw error not retained |
| 5 | deepseek-reasoner | 400 | Rejected; raw error not retained |
| 6 | deepseek-coder | 400 | Rejected; raw error not retained |
| 7 | deepseek-invalid-control-a30 | 400 | Rejected; raw error not retained |
Both successful responses included a system_fingerprint field. The tracker retained only that the field was present and used non-reversible, within-run aliases internally. Raw fingerprints were not published. A fingerprint can help detect a change worth investigating, but it does not expose weights, prove two names are identical, or guarantee immutable routing.
The four failed calls had no recorded token usage and therefore no derived response cost. We intentionally did not preserve provider error wording. Error text can contain implementation detail, identifiers, or content that is unnecessary for the public conclusion. HTTP status, tested identifier, endpoint family, time, and bounded classification were sufficient.
What this was not
This was not a quality benchmark, latency comparison, stress test, regional availability test, or proof of model architecture. Two marker completions cannot rank reasoning or coding ability. Seven calls cannot characterize reliability. The run only checked inventory and compatibility at low cost, then verified removal of the temporary credential in the provider interface.
DeepSeek model and API update timeline
DeepSeek’s historical change log shows why an application cannot treat a convenient alias as an immutable version. The same string was repeatedly routed to new underlying releases before the V4 transition introduced explicit first-class IDs.

| Date | First-party event | Operational meaning |
|---|---|---|
| 2024-05-17 to 2024-07-24 | Chat and coder aliases received several V2-era upgrades | Stable request strings could move between revisions |
| 2024-07-25 | JSON output, function calling, prefix completion, and FIM features announced | Capability change, not model retirement |
| 2024-08-02 | Context caching launched | Cost and latency behavior changed independently of the model string |
| 2024-09-05 | Chat and coder were merged into V2.5, with both aliases retained for compatibility | Two identifiers temporarily converged |
| 2024-12-26 | deepseek-chat upgraded to DeepSeek-V3 | Major family change behind the same alias |
| 2025-01-20 | DeepSeek-R1 launched through deepseek-reasoner | Reasoning alias became a hosted access path |
| 2025-08-21 to 2025-12-01 | Aliases moved through V3.1, Terminus, V3.2-Exp, and V3.2 | More in-place behavior changes |
| 2025-10-15 and 2025-12-15 | Temporary comparison endpoints expired | Endpoint lifecycle can differ from model-name lifecycle |
| 2026-04-24 | deepseek-v4-flash and deepseek-v4-pro launched | Explicit V4 model IDs became the current targets |
| 2026-04-24 | Legacy aliases temporarily mapped to V4 Flash modes | A migration window opened |
| 2026-07-24 15:59 UTC | Announced retirement deadline for chat and reasoner aliases | Applications needed to complete the migration |
| 2026-07-25 23:42 UTC | This tracker ran its bounded live snapshot | Current IDs accepted; tested old names rejected |
The primary chronology is maintained in the DeepSeek change log. The dedicated V4 release notice supplies the V4 mapping and retirement deadline. Release names such as DeepSeek-V3.2 or DeepSeek-R1 must not be assumed to be accepted model values merely because they name a public model family.
Deprecated, removed, rejected, unlisted, and aliased are different

Deprecated means a first-party source warns that an identifier or behavior is being phased out, often with a transition period. Retired or removed means a first-party source states that availability ends, ideally with an effective time and scope. The V4 notice supports the retirement label for the two legacy aliases.
Rejected means a particular request did not succeed. In this run, four identifiers returned HTTP 400. That status alone does not explain why. The deliberately invalid control also returned 400, demonstrating why a tracker must not translate every bad request into “model removed.”
Unlisted means an identifier did not appear in a dated /models response. An account entitlement, rollout, protocol, or future inventory change could affect that response. Unlisted is not a synonym for deprecated.
Aliased means one identifier maps to another target. Use this label as fact only when official documentation states the mapping. Similar output or a matching fingerprint can support an investigation, never definitive identity.
Historical name means a first-party source shows that the identifier existed in an earlier API state. It does not imply present support. deepseek-coder belongs in that class for this test: the 2024 change log documented its compatibility history, current API surfaces omit it, and our exact request was rejected.
A safe status function
function classifyModelStatus({ officialNotice, listed, httpStatus }) {
if (officialNotice?.label === "retired") {
return {
lifecycle: "officially_retired",
observation: httpStatus ? `observed_http_${httpStatus}` : "not_tested"
};
}
if (officialNotice?.label === "deprecated") {
return {
lifecycle: "officially_deprecated",
observation: listed ? "observed_listed" : "observed_unlisted"
};
}
return {
lifecycle: "not_established",
observation: listed
? "observed_listed"
: httpStatus
? `observed_http_${httpStatus}`
: "not_tested"
};
}
The function deliberately returns two fields. Production dashboards should do the same so that a fresh runtime signal cannot overwrite the source-backed lifecycle record.
Migration playbook for a changed DeepSeek model or endpoint
A model migration is a contract change, not a global search-and-replace. The safer workflow keeps the old and candidate configurations versioned until the candidate has passed workload-specific checks and a rollback remains possible.

1. Inventory every dependency
Search application configuration, environment variables, queued jobs, database rows, prompt registries, evaluation fixtures, dashboards, alerts, cost models, SDK wrappers, and documentation. Record the base URL, protocol, model ID, parameters, response parser, tool schema, timeout, and retry policy as one versioned contract.
Queued work deserves special attention. A job created before the migration may contain an old model ID. Decide whether to drain it before the deadline, transform it to a new contract version, or reject it with a recoverable status. Never mutate queued payloads silently after their hash or idempotency key has been established.
2. Select the successor from first-party evidence
Use current documentation and /models, not a plausible release name. For this snapshot, the explicit candidates are deepseek-v4-flash and deepseek-v4-pro. Choose according to the workload’s quality, latency, context, and cost needs; the tiny marker test does not make that choice.
3. Compare request and response contracts
Check allowed parameters, thinking-mode behavior, structured output, tool calls, streaming events, finish reasons, token-usage fields, context limits, and error handling. Validate parsers against captured synthetic fixtures. A candidate that returns HTTP 200 but breaks a tool-call parser has not passed migration.
4. Run shadow evaluations
Replay a privacy-reviewed evaluation set without exposing candidate output to users or triggering tools. Compare exact schema validity, task success, refusal behavior, safety policy, latency distributions, and token use. Use deterministic scoring where possible and human review where the task is subjective.
5. Canary real traffic
Route a small, reversible percentage through the new contract. Separate metrics by model-contract version. Stop automatically on parser errors, policy regressions, unacceptable task quality, cost drift, or latency breaches. Do not rely on the requested model string alone when interpreting telemetry.
6. Cut over, observe, then retire
Increase traffic in stages, retain the rollback route, and watch queues created under the old version. Remove the old identifier only after outstanding work is drained or deliberately transformed. Update runbooks and alerts so an HTTP 400 from a stale worker does not become a blind retry loop.
Rollback conditions
Rollback should be automatic or immediately available when the candidate violates a hard contract: authentication or route failure, incompatible response shape, invalid tool arguments, structured-output regression, safety threshold breach, unbounded cost increase, or sustained reliability failure. A provider retirement can make the former model unavailable; in that case rollback may mean pausing the affected feature or switching to a tested fallback, not restoring the retired alias.
Practical contract tests before switching production traffic
The following matrix is a starting point. Replace NOT TESTED with evidence from your own workload; this tracker did not claim those broader tests were performed.

| Contract | Minimum candidate test | Release gate |
|---|---|---|
| Authentication and route | Minimal authorized call | Expected success and safe failure handling |
| Model inventory | Candidate appears in dated /models response | Exact ID recorded |
| Request parameters | Exercise every production parameter | No unsupported-field surprises |
| Response schema | Parse normal and terminal fixtures | Zero parser failures |
| Streaming | Parse deltas, keep-alives, and termination | No truncated or duplicated output |
| Tool calls | Validate names, arguments, and finish state | No unvalidated side effect |
| Structured output | Run representative JSON fixtures | Workload threshold met |
| Quality and safety | Run versioned evaluation set | Approved thresholds met |
| Latency and reliability | Measure p50, p95, and error rate | Service objectives met |
| Tokens and cost | Compare normalized usage | Budget threshold met |
| Retry behavior | Exercise terminal, transient, and unknown outcomes | No unsafe replay |
A minimal inventory and marker test
const baseURL = "https://api.deepseek.com";
const apiKey = process.env.DEEPSEEK_API_KEY;
async function deepSeek(path, init = {}) {
const response = await fetch(`${baseURL}${path}`, {
...init,
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
...init.headers
}
});
return { status: response.status, json: await response.json() };
}
const inventory = await deepSeek("/models");
if (inventory.status !== 200 || !Array.isArray(inventory.json.data)) {
throw new Error("Model inventory contract failed");
}
const expected = "MIGRATION_CHECK_OK";
const probe = await deepSeek("/chat/completions", {
method: "POST",
body: JSON.stringify({
model: "deepseek-v4-flash",
messages: [{
role: "user",
content: `Reply with exactly ${expected}`
}],
stream: false,
temperature: 0,
max_tokens: 16
})
});
const text = probe.json?.choices?.[0]?.message?.content?.trim();
if (probe.status !== 200 || text !== expected) {
throw new Error("Marker contract failed");
}
Use a dedicated, short-lived credential for a scheduled audit and disable automatic SDK retries so the call budget stays auditable. Never log apiKey, raw Authorization headers, or unreviewed response bodies.
A small production contract harness
from dataclasses import dataclass
from typing import Callable
@dataclass
class ContractResult:
name: str
passed: bool
detail: str
def run_contracts(call: Callable, model: str) -> list[ContractResult]:
results = []
response = call(
model=model,
messages=[{"role": "user", "content": "Return exactly CONTRACT_OK"}],
temperature=0,
max_tokens=16,
stream=False,
)
results.append(ContractResult(
"http_and_marker",
response.status_code == 200
and response.output_text.strip() == "CONTRACT_OK",
f"status={response.status_code}",
))
results.append(ContractResult(
"usage_shape",
response.usage is not None
and response.usage.total_tokens >= 1,
"sanitized usage fields only",
))
return results
Extend this harness with your tool schemas, structured-output fixtures, long-context cases, safety checks, and streaming parser. Keep fixtures synthetic or properly authorized. A single marker is a connectivity contract, not an evaluation of model quality.
Endpoint and protocol traps
DeepSeek documents OpenAI-compatible and Anthropic-compatible formats, but compatibility behavior can differ. The Anthropic API guide describes model-name mapping and fallback behavior. A random name accepted through a compatibility layer may prove only that fallback mapping occurred.
For that reason, negative identifier probes in this tracker used the OpenAI-format Chat Completions endpoint. When migrating an Anthropic-compatible integration, test the exact protocol and record the returned model metadata. Do not infer that an accepted SDK call means the literal requested identifier is a supported first-class DeepSeek API ID.
Parameters can also be deprecated independently of models. A model can remain current while one request field becomes ignored, rejected, or reinterpreted. Treat model inventory, endpoint shape, parameter support, pricing, limits, and response semantics as separate tracker dimensions.
How this tracker stays current

The maintenance policy is designed to show what was actually refreshed:
- Weekly: reread the first-party change log, model reference, Chat schema, pricing page, limits, and error documentation.
- Monthly: with explicit authorization, create a dedicated temporary key and repeat a bounded inventory and marker snapshot.
- Event driven: review immediately after a first-party release, deprecation notice, unexplained production change, or model-list difference.
- Quarterly: audit source links, timeline dates, contract code, schema, and correction history.
- Stale flag: mark live evidence as stale after 31 days even if the article prose was edited more recently.
Every revision should append a compact change ledger:
| Field | Meaning |
|---|---|
| Documentation reviewed | Sources were reread; no API call implied |
| Live snapshot repeated | Inventory and bounded probes were actually rerun |
| Prose corrected | Wording changed; evidence timestamp did not |
| Model-list changed | Added or removed exact IDs shown as a diff |
| Lifecycle notice changed | First-party label or effective date changed |
The visible dateModified value is not enough. A spelling fix must never make a three-month-old runtime test look fresh. The separate evidence window is the authoritative timestamp for observed behavior.
Operational alerts for DeepSeek API updates
Use severity based on impact rather than novelty:
| Severity | Example | Recommended action |
|---|---|---|
| Critical | Current production ID rejected or removed from inventory | Freeze rollout, activate tested fallback, investigate |
| High | Official retirement notice affects a configured ID | Start migration and deadline tracking |
| Medium | Price, concurrency, context, or response contract changes | Recalculate and rerun affected tests |
| Low | Documentation wording or example changes without contract impact | Review and record |
Alert on structured diffs, not screenshots. A useful event includes the exact surface, previous sanitized value, current sanitized value, source URL or test time, and the contract owner. Never attach an API key, raw headers, account balance, unreviewed response, or raw system fingerprint.
Limitations
This tracker is deliberately bounded:
- API availability can vary by account, entitlement, protocol, region, capacity, and date.
/modelsis a point-in-time inventory result, not a provider lifecycle policy.- A successful request does not guarantee future acceptance or unchanged behavior.
- A rejection does not independently establish deprecation, permanent removal, or the reason for failure.
- Matching outputs or fingerprint groups do not prove alias identity or identical model weights.
- The tests cannot inspect model weights, hidden routing, provider intent, or future rollout plans.
- Historical documentation may omit transitional behavior.
- Pricing, limits, parameters, and error contracts can change independently of a model identifier.
- The two marker calls measured compatibility, not quality, safety, latency, or reliability.
- The derived cost used dated public list rates and is not an invoice.
The practical rule is simple: preserve the source, label the scope, test the candidate contract, canary the migration, and keep rollback available. Never promote a dated observation into an official lifecycle claim.
Frequently asked questions
What are the latest DeepSeek API updates?
As reviewed on July 25, 2026, the current first-class API IDs are deepseek-v4-flash and deepseek-v4-pro. DeepSeek’s official V4 notice retired the legacy chat and reasoner aliases after July 24, 2026 at 15:59 UTC. Our next-day snapshot listed and accepted both V4 IDs while both retired aliases returned HTTP 400.
Which DeepSeek models are currently available through the API?
The current documentation and our dated /models response identify deepseek-v4-flash and deepseek-v4-pro. The inventory is specific to the tested account and time, so verify the official model reference and your authenticated model list before deploying.
How can I check the DeepSeek model list?
Send an authenticated GET request to https://api.deepseek.com/models and read the exact IDs in the returned data array. Keep the API key out of logs and publications, sanitize the result, and record the UTC timestamp because inventory can change.
Does a model missing from /models mean it is deprecated?
No. It means only that the identifier was absent from that dated response. An official deprecation requires first-party lifecycle wording. Record “observed unlisted” separately from “officially deprecated” or “officially retired.”
Does an HTTP error mean a DeepSeek model was removed?
No. Authentication, balance, payload, parameter, entitlement, and transient problems can also produce errors. In our run, old names and an invalid control returned HTTP 400; the retirement label for chat and reasoner comes from the official V4 notice, not from status 400 alone.
What is the difference between a deprecated and a removed DeepSeek model?
Deprecation is an official transition warning that usually gives users time to migrate. Removal or retirement states that availability ends for a defined scope, often on an effective date. Preserve the provider’s wording instead of treating the terms as interchangeable.
How does this tracker verify old DeepSeek model IDs?
It tests only exact identifiers found in current or historical first-party DeepSeek sources, plus one clearly labeled invalid control. Each candidate receives one minimal deterministic request, automatic retries are disabled, and only privacy-safe status, marker, usage, and timing fields are retained.
Can two DeepSeek model IDs be aliases?
Yes, when DeepSeek’s documentation says one identifier maps to another target. Without that statement, similar behavior or metadata can support only an alias hypothesis. The tracker does not turn correlation into identity.
Does the same system_fingerprint prove two model names are identical?
No. A fingerprint can be a useful within-run change signal, but it does not reveal weights, routing policy, immutable versions, or future behavior. This project never publishes raw fingerprint values.
How often is the DeepSeek API updates tracker refreshed?
The policy is weekly first-party documentation checks, monthly authorized live snapshots, immediate event-driven review, and a quarterly audit. Live evidence receives a visible stale warning after 31 days even if the prose has been edited.
What should I test before migrating to a new DeepSeek model?
Test authentication, route, parameters, response and streaming schemas, tool calls, structured output, workload quality, safety, latency, token use, cost, limits, retries, and unknown outcomes. Use shadow evaluation and a reversible canary before full cutover.
Should I use an alias or a pinned DeepSeek model ID in production?
Use the most explicit current identifier the provider documents for your endpoint. Aliases can ease upgrades but may move between backends. Explicit IDs improve clarity, although they are not necessarily immutable unless DeepSeek documents that guarantee.
How should I handle queued requests that contain an old model ID?
Inventory them before cutover, then drain, transform, or reject them through a versioned migration. Preserve idempotency keys and payload hashes, make transformations explicit, and keep rollback controls so redelivery does not create duplicate work.
Can a successful request prove that an old DeepSeek model will keep working?
No. It proves only observed acceptance for one endpoint, account context, payload, and time. Future availability requires current first-party evidence and repeated contract checks.
Where should I monitor official DeepSeek API changes?
Monitor the official change log, model-list reference, Chat Completion schema, pricing page, error codes, and service status.
