Kimi Files API: Upload, Extract, Q&A & Delete

The Kimi Files API provides a programmatic lifecycle for uploading a file, retrieving its extracted text, using that text in a model request and deleting the uploaded resource. The important implementation detail is that upload alone does not make a file answer accurate: your application must retrieve the extracted content, pass the relevant text to the model and validate the answer independently.

We ran one fail-closed PDF lifecycle against the Global Kimi API. Upload and content retrieval each returned HTTP 200, and the extracted text contained all 10/10 frozen markers. One kimi-k3 Q&A request passed 2/5 strict answer-shape checks at a usage-derived cost of $0.007461. The delete request returned HTTP 200, but the one preregistered GET /files/{id} verification returned HTTP 500 instead of 404. We stopped there. DOCX and CSV were not run.

Independent test result, August 7, 2026: PDF upload 200; content retrieval 200; extraction 10/10; Q&A HTTP 200 and 2/5 under the frozen strict oracle; delete 200; one deletion-verification GET 500. No retry or corrective run was made. A separate read-only GET /files later showed zero listed files and zero listed bytes at 2026-08-07T17:34:02.286Z. That later inventory does not turn the failed single-resource verification into a pass.

Kimi AI Guide is independent and is not affiliated with Moonshot AI or Kimi.

Result at a glance

StagePDF observationClassification
POST /files with purpose=file-extractHTTP 200Upload request passed once
GET /files/{id}/contentHTTP 200Content retrieval passed once
Frozen extraction markers10/10 presentExtraction marker check passed
POST /chat/completionsHTTP 200; kimi-k3; finish_reason: stopTransport completed once
Strict Q&A oracle2/5Failed strict answer contract
Usage-derived Q&A cost$0.007461Dated calculation, not a billing-posting claim
DELETE /files/{id}HTTP 200Delete request succeeded once
One GET /files/{id} verificationHTTP 500; expected 404Verification failed; no retry
Independent later GET /files0 files; 0 bytesPoint-in-time empty list, not a 404 substitute
DOCX fixtureNOT RUNNo acceptance, extraction, Q&A or cleanup result
CSV fixtureNOT RUNNo acceptance, extraction, Q&A or cleanup result

The defensible conclusion is narrow: one synthetic PDF uploaded and extracted successfully; its strict Q&A contract failed 3 of 5 fields; deletion returned 200 but the required follow-up resource check returned 500; the later file list was empty. This is not a cross-format reliability rate.

This page is for the API, not consumer Kimi file upload

This page owns developer intent: HTTP endpoints, purpose=file-extract, extracted-content handling, model context, strict scoring, resource deletion and cleanup evidence.

For uploading a document in the Kimi web interface, dealing with long-document context or choosing a consumer workflow, use Using Kimi with Files and Long Documents. A successful browser upload and a successful API lifecycle are different products and should not be treated as interchangeable tests.

For API authentication and a first text request, start with the Kimi API guide. This page assumes that your server already holds a valid API key securely.

The documented Files API lifecycle

Kimi’s current Files upload reference documents POST /files with the upload purpose file-extract. The current per-file limit shown there was 100 MB when checked on August 7, 2026. A size ceiling is not a guarantee that a scanned page, table, chart, formula or unusual encoding will extract correctly.

Kimi’s file-based Q&A guide uses this sequence:

  1. upload the file for extraction;
  2. retain the returned file ID only as long as the application needs it;
  3. retrieve the extracted content;
  4. place the relevant extracted text in the model context;
  5. ask a bounded question;
  6. validate the output against your own rules; and
  7. delete the uploaded file when its lifecycle ends.

Do not assume that a chat request can use an uploaded file merely because a file_id exists. In the documented flow tested here, the application retrieves the content first and supplies that text to the model.

A minimal server-side implementation pattern

The examples below show the request boundaries; they are not a client-side browser integration. Keep the API key on your server and never place it in WordPress, public JavaScript, a downloadable fixture or a log shared with users.

1. Upload once for extraction

upload_file="synthetic-fixture.pdf"

curl --fail-with-body \
  --request POST "https://api.moonshot.ai/v1/files" \
  --header "Authorization: Bearer $MOONSHOT_API_KEY" \
  --form "purpose=file-extract" \
  --form "file=@${upload_file};type=application/pdf"

Check the HTTP status and parse the returned ID. Store that ID in a private, run-scoped cleanup record immediately. Never add a manually supplied, pre-existing or list-discovered ID to an automated deletion queue.

2. Retrieve and validate extracted text

curl --fail-with-body \
  --request GET "https://api.moonshot.ai/v1/files/$FILE_ID/content" \
  --header "Authorization: Bearer $MOONSHOT_API_KEY" \
  --header "Accept: application/json, text/plain"

Treat extracted text as untrusted input. Before asking a model a high-stakes question, check deterministic anchors such as a document identifier, named section, total row or verification phrase. That does not prove every character is correct, but it can stop a clearly incomplete extraction from reaching the model.

3. Put the extracted content in a bounded model request

Our live runner used one kimi-k3 call with reasoning_effort: low, a 600-token maximum and response_format: {"type":"json_object"}. The relevant shape was:

const payload = {
  model: "kimi-k3",
  reasoning_effort: "low",
  max_completion_tokens: 600,
  messages: [
    {
      role: "system",
      content:
        "Use only the following extracted synthetic file content. " +
        "Do not use outside facts.\n\n" + extractedText
    },
    {
      role: "user",
      content: JSON.stringify(frozenQuestionContract)
    }
  ],
  response_format: { type: "json_object" }
};

json_object ensured that the outer response could be parsed as JSON; it did not enforce the required nested types. That distinction explains our result: the response had the five expected top-level keys, but three values were prose strings where the frozen oracle required objects.

If exact structure matters, validate it locally and use the current Kimi API structured-output guidance where the selected model and schema subset support it. Valid JSON is not the same as schema compliance, and schema compliance is not the same as factual correctness.

4. Delete only the resource your run created

curl --fail-with-body \
  --request DELETE "https://api.moonshot.ai/v1/files/$FILE_ID" \
  --header "Authorization: Bearer $MOONSHOT_API_KEY"

Kimi’s Files deletion reference provides the deletion operation. Your application should still record the response, make a bounded verification appropriate to the documented contract and keep an explicit unresolved state if verification fails.

Do not blindly retry a deletion after an uncertain transport result. A retry may target a resource already deleted, and the second response can obscure what happened on the first attempt.

Our synthetic PDF fixture

The exact one-page PDF used in this run is available as the synthetic PDF fixture and is also included in the sanitized evidence package as fixtures/kimi-files-api-ground-truth-fixture.pdf.

Fixture propertyFrozen value
Fixture IDKIAI-FILES-20260807-PDF-01
SyntheticYes; no real person, account or operational record
Size3,503 bytes
SHA-2563740399D20CD8CDB9E5DD6003D53BAF04264F6FA10233AC219286DE39BA891AE
Pages1
Reporting date inside fixtureAugust 1, 2026
Verification phraseORBIT-SAFFRON-4821
DataThree sites, planned/actual units, defects and synthetic owners

The PDF was rendered at 144 DPI and inspected at original resolution before the API run. Local QA found no clipping, overlap, broken table cells, unreadable text, missing footer or page-number defect. Its locally extracted text contained 1,298 characters and all required ground-truth anchors.

The fixture’s simplicity is deliberate. It lets us separate an API or model error from a changing source, OCR ambiguity or an unknown expected answer. It does not represent a scanned report, multi-column paper, image-only PDF or long document.

Frozen test methodology

SettingFrozen value
Run IDkimi-api-reliability-lab-20260807-v1-files
DateAugust 7, 2026
API regionGlobal, https://api.moonshot.ai/v1
Planned orderPDF, DOCX, CSV
Upload purposefile-extract
Q&A modelkimi-k3
Reasoning effortlow
PDF maximum completion600 tokens
Q&A calls per fixture1
Upload/content/delete/verify attempts1 each
Automatic or corrective retries0
ExecutionSequential, fail closed
PDF extraction oracle10 exact markers
PDF answer oracle5 precomputed questions with exact types and values

For each fixture, the planned runner verified local hashes, uploaded once, retrieved content once, checked extraction markers, made one bounded Q&A request, scored the unedited response, deleted only the ID created by that run and made one resource-verification GET.

The required cleanup-verification status was HTTP 404. Because the PDF verification returned HTTP 500, the runner stopped before opening the DOCX or CSV stages. We did not relax the condition, retry the request or record the remaining formats as failures.

Extraction result: 10/10 markers were present

The content endpoint returned HTTP 200. The extracted text contained every preregistered marker:

Marker classRequired valuesResult
Document identityKIAI-FILES-20260807-PDF-01, ORBIT-SAFFRON-48212/2
Site namesCairo, Alexandria, Aswan3/3
Totals295 planned, 287 actual2/2
Synthetic ownersMira Chen, Omar El-Sayed, Lina Park3/3
Total10 exact markers10/10

This passed a marker-presence check. It does not prove byte-for-byte extraction, correct reading order, complete formatting, or performance on other PDFs.

Strict Q&A result: 2/5

The chat request returned HTTP 200 with model kimi-k3 and finish_reason: stop. The response parsed as a JSON object and included all five expected top-level keys. The strict nested answer checks produced this result:

QuestionRequired resultObserved resultStrict result
Document ID and verification phraseObject with two named fieldsString: KIAI-FILES-20260807-PDF-01; ORBIT-SAFFRON-4821Fail
Total actual unitsNumber 287Number 287Pass
Site above plan and amountObject: Alexandria, 6String: Alexandria, by 6 unitsFail
Sites meeting review ruleArray ["Cairo"]Array ["Cairo"]Pass
Zero-defect owner and countObject: Lina Park, 0String: Lina Park, 0 defectsFail

The three failed strings contain the expected human-readable facts, but they violate the requested JSON types and field structure. We did not convert them into passes after seeing the response. For an application that reads answer.q3.site, a correct-looking sentence is still a contract failure.

This single result does not show that K3 usually scores 40% on file questions. It shows that one json_object response preserved the requested top-level keys but failed three nested shape requirements. A larger, preregistered sample would be needed for a rate.

Usage and cost

The one Q&A request reported:

Usage fieldTokens
Prompt707
Cached prompt0
Uncached prompt707
Completion356

Using the pricing snapshot frozen for the run—$3.00 per million uncached K3 input tokens, $0.30 per million cached input tokens and $15.00 per million output tokens—the usage-derived calculation is:

707 × $3.00 / 1,000,000  = $0.002121
0 × $0.30 / 1,000,000    = $0.000000
356 × $15.00 / 1,000,000 = $0.005340
Total                     = $0.007461

This is the calculated model-inference cost for the retained Q&A usage. It is not a claim about a separate file-processing fee, an immediate console deduction or future pricing. Check the current Kimi API pricing and limits before setting a production budget.

Delete returned 200; the required verification returned 500

The runner recorded the uploaded PDF’s provider-generated ID in a private cleanup ledger and used only that run-owned ID for cleanup. The ID is excluded from the public package.

The single delete request returned HTTP 200. The runner then made its one preregistered GET /files/{id} check. Expected: 404. Observed: 500. The runner recorded deletion verification as failed and stopped.

We do not claim that the GET returned 404. We do not claim that HTTP 500 means the file still existed. The retained result does not expose a response body that would justify a more specific explanation.

The later list check was empty, but answers a different question

An independent read-only GET /files check returned:

{
  "observed_at_utc": "2026-08-07T17:34:02.286Z",
  "listed_file_count": 0,
  "listed_file_bytes": 0
}

This establishes that the list endpoint exposed no files at that timestamp. It supports the operational observation that no test file remained visible in the account inventory. It does not prove:

  • that the single-resource endpoint would return 404 on another request;
  • why the recorded request returned 500;
  • immediate or permanent backend erasure;
  • provider retention behavior; or
  • a general cleanup success rate.

Both facts belong in the record: the required resource verification failed, and the later list view was empty.

Why DOCX and CSV are NOT RUN

The frozen protocol was sequential and fail closed. It did not authorize continuing to the next upload after unresolved cleanup verification.

FormatUploadExtractionQ&ADelete/verifyFinal status
PDF20010/10 markers2/5 strictDelete 200; verify GET 500Partial lifecycle completed; verification failed
DOCXNot attemptedNot attemptedNot attemptedNot attemptedNOT RUN
CSVNot attemptedNot attemptedNot attemptedNot attemptedNOT RUN

NOT RUN is not a zero score and not evidence of incompatibility. We make no claim about DOCX or CSV upload acceptance, extraction quality, model answers, cost or deletion behavior from this run.

What this test supports—and what it does not

Supported by the retained evidence:

  • one 3,503-byte synthetic PDF upload returned HTTP 200;
  • its content endpoint returned HTTP 200;
  • all 10 frozen extraction markers were present;
  • one K3 Q&A call returned valid top-level JSON and passed 2/5 strict nested checks;
  • the recorded Q&A usage produced a $0.007461 dated cost calculation;
  • one delete request returned HTTP 200;
  • one resource-verification GET returned HTTP 500 rather than 404;
  • no retry or correction was made;
  • the protocol stopped before DOCX and CSV; and
  • a later independent list check exposed zero files and zero bytes.

Not supported:

  • a general Files API success, accuracy or deletion rate;
  • byte-perfect extraction or OCR performance;
  • DOCX or CSV compatibility;
  • a claim that all five answers passed because their prose looked correct;
  • a claim that deletion was verified with HTTP 404;
  • an explanation for the HTTP 500;
  • proof of backend erasure or a retention-policy conclusion;
  • file-processing pricing beyond the retained model usage; or
  • behavior in another account, region, model or date.

Production safeguards

  • Upload from a trusted server; never expose the API key in public JavaScript.
  • Restrict accepted file type, byte size and filename before sending data.
  • Use synthetic or minimized data for the first integration test.
  • Record the local source hash before upload and keep the provider ID private.
  • Retrieve extracted text and validate deterministic anchors before Q&A.
  • Treat file text as untrusted input that may contain prompt injection.
  • Bound model, context, output tokens, time, spend and attempt count.
  • Validate parse, schema and facts separately; do not accept fluent prose when an object is required.
  • Delete only IDs created by the current workflow and never ingest arbitrary IDs into cleanup.
  • Keep delete accepted, resource verification and list inventory as separate states.
  • Do not retry an uncertain delete automatically.
  • Redact keys, Authorization headers, provider IDs, request IDs, reasoning and account data from public evidence.
  • Review the provider’s current data-use and retention terms before uploading confidential or regulated material.

For error-handling patterns, use the Kimi API Error Decoder. For model-generated custom functions, see Kimi API Tool Calling.

Frequently asked questions

Does uploading a file automatically make it available to a Kimi chat request?

The documented flow used here retrieves the extracted content and supplies that text in the model context. An upload ID alone is not evidence that the model read the file.

Did the PDF extraction pass?

It passed the frozen 10-marker presence check. That is narrower than byte-perfect extraction, layout preservation or a long-document benchmark.

Why is the Q&A score 2/5 if all three failed strings show the right facts?

Because the preregistered contract required objects with named fields. Three answers returned strings instead. Applications depend on types and keys, so we preserved those failures rather than rescoring them after the run.

Was the uploaded PDF deleted?

The delete request returned HTTP 200, and a later independent list request exposed zero files and zero bytes. However, the required one-resource verification returned HTTP 500 rather than 404. We therefore report the deletion request as accepted but the preregistered 404 verification as failed.

Did you test DOCX and CSV?

No. The fail-closed protocol stopped after the PDF verification error. Both formats are NOT RUN.

Should an application retry HTTP 500 after deleting a file?

Not automatically. The delete may already have taken effect. Preserve the first result, check the current official contract and use a bounded, explicitly authorized reconciliation process that cannot delete an unrelated resource.

Is the $0.007461 figure a provider invoice?

No. It is calculated from the API-reported token usage and the dated pricing snapshot frozen for the run. It does not establish a separate file-processing charge or the timing of an account deduction.

Downloadable evidence

Download the Kimi Files API Evidence Bundle. It is 11,814 bytes with SHA-256 DE87D50D9CAB61BF07D263C02186FCC32CFD71DC3EB918D033CCC46874ED5CA1. It contains the exact PDF, ground truth, frozen oracle, fixture QA, sanitized result, methodology, manifest and SHA-256 checksums. A fresh public download matched the local byte count and hash exactly.

The package excludes the API key, Authorization header, provider-generated file ID, private cleanup ledger, account/project identifiers, balance data, provider request IDs and returned reasoning content.

Official sources and evidence boundary

The endpoint descriptions above come from current official documentation checked on August 7, 2026. Every HTTP status, score, token count, cost calculation, timestamp and limitation in the result sections comes from this independent single-pass run or its explicitly identified later read-only list observation.