Undocumented batch behavior: output_file_id not returned at creation, must query /v1/batches/{id} to detect errors

I would like to report a critical gap in the OpenAI API batch documentation and behavior that affects the reliability of automated systems managing batch processing.


Observed behavior

  1. Until a few months ago, the POST /v1/batches endpoint would return a batch_object including the output_file_id (if the batch was valid and successfully accepted).
  2. As of now, this is no longer the case:
  • The creation response includes only the batch id (e.g. "id": "batch_xyz123").
  • The output_file_id, or any indication of a failure, is not included in the initial response.
  • Any error (e.g. invalid input format, token over-limit) is not returned in the POST response.
  1. The only way to determine whether the batch was accepted, rejected, failed, or validated is to explicitly query the batch again using GET /v1/batches/{id}.

Why this is problematic

  • The official documentation does not explain this required follow-up step.
  • This creates confusion and breaks systems expecting either:
    • An immediate output_file_id on successful creation
    • An error in the POST response when the batch is invalid
  • Without polling GET /v1/batches/{id}, there is no way to:
    • Detect validation errors
    • Know if the batch failed to start
    • Obtain the error_file_id to inspect what went wrong

Expected behavior or documentation fix

One of the following should be done:

  1. The POST /v1/batches response should immediately reflect the true status of the batch (even if just “validating” with a reference to future errors), or
  2. The documentation should explicitly state that:
  • The output_file_id will not be present in the creation response
  • The batch must be polled with GET /v1/batches/{id} to detect completion or failure
  • The error_file_id is only retrievable via this second query

Tested conditions

  • Multiple batches submitted with invalid JSONL (or excessive tokens)
  • Files manually deleted during validation phase
  • POST always succeeds with a new batch id, but the batch silently fails, only visible after polling

Conclusion

This undocumented behavior may lead to misleading assumptions and failure to capture critical errors in batch processing automation. Clarifying this in the documentation (and ideally improving the POST response) would significantly enhance developer experience and reliability.

Sergio Bonfiglio

1 Like

Hey Sergio

This is Diana from the user operations team.

Thank you for flagging this gap in our Batch API docs and for outlining your test results so clearly. You’ve surfaced two distinct issues:

As-submitted behaviour – POST /v1/batches returns only a batch ID because validation happens asynchronously.

Documentation clarity – our public guide doesn’t yet spell out that you must poll the batch object (or download its error/output files) to learn the final state.


Below is a detailed explanation you can pass to your automation team, plus a quick look at what we’re doing to improve the docs and developer experience.

After the batch is queued, the service validates every task (JSONL well-formedness, token limits, duplicate custom_id, etc.). That work can’t finish inline with the request, so the creation call only tells you that the job entered the queue. output_file_id (and error_file_id, if any) are created after validation. Until then, those IDs simply don’t exist, so they can’t be returned in the initial payload.


We recommend to poll GET /v1/batches/{id} until the batch reaches a terminal state (completed, failed, or expired).

Attaching an example below

# 1️⃣ Create the batch

curl https://api.openai.com/v1/batches \

-H "Authorization: Bearer $OPENAI_API_KEY" \

-H "Content-Type: application/json" \

-d '{

"input_file_id": "file-abc123",

"endpoint": "/v1/chat/completions",

"completion_window": "24h"

}'

# → response

{

"id": "batch_xyz123",

"object": "batch",

"status": "validating", # may be "queued" in older SDKs

"input_file_id": "file-abc123",

...

}
# 2️⃣ Poll for status (suggested cadence: start at 5 s back-off, cap at 30 s)

curl https://api.openai.com/v1/batches/batch_xyz123 \

-H "Authorization: Bearer $OPENAI_API_KEY"

​

1 Like

There are likely more calls where the expected object that would indicate success within doesn’t have the data. For example:

  • adding file attributes (metadata) to a vector store in a “modify” call returns a vector store object without those same attributes just sent.

The API thus is basically, “this previous state of the object won’t be useful to you, but have it anyway.” For changing settings where you expect to be able to employ the return.

Dear Diana,

first thanks a lot for your reply.
It is important to address some important things about the documentation.
In the “batch” page the fact that the process is asynchronous is not well specified.
Also in the batch activation object returned, there are fields such as output_file_id and error_file_id that should be deprecated, because they are severely misleading for those who read the documentation.
If you put some “output” entity in the activation-relpy, the reader is authorized to think that it must be there, in case everything is OK.
So the fact that the fields are empty makes the reader to think that something went wrong or problematic.
The second problem of the activation-reply is that the name field “id” is inconsistent and severely misleading again.
“id” of what?
This field should be replaced with a more consistent “activated_batch_id_name” fieldname that takes away every doubt about what is the content of that field referring to.
Third problem: your language examples cover too few languages.
We’re using C++, C#, Delphi, ColdFusion etc. Why in the name of God you don’t provide examples with these languages? Also a set of components to use the API service would increase your business immensely, because there wouldn’t be any need to “reinvent the weel” to consume your services.
Fourth problem: documentation clarity
It is ridiculous (sorry to be so frank) that an Organization like yours is missing clarity right in the documentation part. We are not talking with some understair, backroom company. We are speaking with the number 1 AI company of the planet, so “honors and burdens” impose you must invest a lot more in the documentation section.
A good part of the planet is relying on You for our growth in business and knowledge.
You can’t leave us “on the road”, trying to figure out what a hack is going on into your system.
Seriousness requires it.

Hey there

First, thank you for taking the time to articulate these pain-points so clearly. We agree that great documentation is as important as great APIs, and your feedback is exactly what helps us close the gaps.

You’re right—the current “Batch” reference buries this fact. We’ve already queued an edit so the very first sentence calls this out (“Create large batches of API requests for asynchronous processing …”) and emphasises the 24-hour completion window.

What you can rely on today

status tells you where the job is (queued → in_progress → finalizing / completed / failed).

output_file_id & error_file_id remain null until the batch is finished (see next section).

output_file_id / error_file_id field confusion

Those fields exist because the service can write your successful tasks and first-page errors to files. When a batch is still running, they’re empty—nothing has gone wrong.

We recognise the naming is misleading & i'll forward that feedback to our team.

The id field

id is the unique identifier of the batch job itself. For individual requests inside the batch we expose custom_id (your row’s identifier) so you can reconcile results. Our specification explicitly calls out this separation: id is globally unique, custom_id is file-unique. We'll make some changes here.
​

We currently publish fully-maintained SDKs for Python, JavaScript, Ruby, and Go. Many teams—including Delphi/C++ shops—successfully call the REST endpoints directly because every operation is just HTTPS + JSON. That said, you’re right that having “copy-paste-able” snippets lowers the barrier.

Thanks again for holding us to a higher bar. Your success is literally the reason we ship improvements like these.

1 Like