What to check
- ✓Add every vector store together, then subtract one free gigabyte. Splitting stores does not grant another free gigabyte. Compare parsed chunks and embeddings, not the raw upload.
- ✓On a day with zero queries, storage should still be there once you are past the free gigabyte. A missing
file_search_calldoes not explain that line. - ✓Count
file_search_callitems in the response. Do not count the tool sitting intools. The per-call price is documented for the Responses API. - ✓After you lower
max_num_results, check that model input dropped. The call line does not discount by how many chunks came back. - ✓Storage stops for a store after it expires or you delete it and the indexed files are gone. Days already posted are not reversed by a later delete.
1. Storage is not the file you uploaded
The retrieval guide treats a vector store as the container for semantic search. A file added to it is chunked, embedded, and indexed. Storage is the total across all of your vector stores, based on the size of parsed chunks and their embeddings. It is not the byte size of the original Files API object. A PDF with finer chunks and more overlap can index larger than the file you uploaded. Dividing the raw file by the number of days will not match.
The free allowance is a total, not a per-store coupon. The guide says the first 1 GB across all stores is free, and usage beyond that bills per day. On the pricing page checked 2026-10-23, that overflow is listed at $0.10 per GB per day, and a GB there is 2^30 bytes. Splitting one store into five does not turn the free gigabyte into five. A day with no searches still bills storage once the total sits above the free gigabyte. The clock is on the store, not on the request.
The objects are different. A file is a Files API object, also used for fine-tuning and other jobs. A vector_store.file is that file after it has been chunked, embedded, and attached to a store. An upload that never enters a vector store is outside this storage line. Once it is in a store, the parsed index occupies the shared gigabyte even if nobody searches.
2. Declaring the tool is not a call
The file search guide defines the tool on the Responses API. The model decides whether to use it. When it does, the response has a file_search_call item and a message with file_citation annotations. Putting type: file_search in tools only makes the tool available. The call fee follows file_search_call items in the output, not the declaration. The sample queries array is the query strings on that call. The docs do not define the array length as the billable count, so do not multiply the price by how many strings you see.
The pricing page splits file search into storage and tool calls. On the day this was checked, tool calls were listed at $2.50 per 1,000, and the note says that call price applies to the Responses API only. The retrieval guide also documents a direct search on a vector store. That is a different path. The pricing page does not put it on the same call rate. Storage does not care which path you query through. If the store exists, it is in the total.
The model can search more than once in a single turn, which produces more than one file_search_call. Each item is evidence of a call. Leaving the tool in the default list lets the model add calls you did not type. “I asked one question” is not the call column.
3. Fewer results shrink input, not the call
The file search guide says max_num_results can reduce token usage and latency, at the cost of answer quality. That is the text sent into the model. It is not a discount on the call. Setting it to 2 still counts as one file_search_call. What gets smaller is the input that follows.
A higher score_threshold in the retrieval guide keeps fewer chunks and can drop useful ones. Fewer chunks mean a shorter context. The pricing page says tokens used for built-in tools are billed at the chosen model’s input and output rates. Retrieved text is content fed to the model, added to the input of that request beside your own prompt. A file_citation in the answer is an annotation, not a fourth fee. The citation can be short while input tokens are long, because the retrieved chunks are not expanded inside the annotation.
One search therefore has two lines, and a third whenever the store is still there. The call is the file_search_call. The model line is input and output, and the input includes what was retrieved. Storage is whether parsed bytes across every store exceed the shared gigabyte, regardless of how many chunks this call returned. The three lines share a product name. Adding them into the model total will not reconcile.
4. Expiry deletes the index, not the days already billed
The retrieval guide lets you set expires_after on a vector store. The sample anchor is last_active_at, with days set to 7. Once the store expires, associated vector_store.file objects are deleted, and the guide says you are no longer charged for them. The anchor is last activity, so that policy is not an upload-date timer. The docs do not define every API action as a refresh of last_active_at. Do not assume that only a user question counts, or that every list request extends the store. Storage has stopped for that index when the store has expired and the files are gone.
Deleting the store is the other stop. Pricing is the total of stores that still exist. A delete removes that parsed index from the total. The sentence about no longer being charged describes storage after the index is gone. It does not refund days already posted above the free gigabyte. Delete today, and the days before today remain.
Chunking changes how fast you cross the gigabyte. More overlap stores the same passage more than once, so the parsed size can pass 1 GB sooner. Raising chunk_overlap_tokens to improve recall changes the storage line. It does not make calls cheaper. Estimating the free gigabyte from the raw file size usually undercounts.
5. A top-up does not merge the three lines
Reconcile three columns. First, parsed size across every vector store, minus the shared free gigabyte. The overflow is daily, including days with no queries. Second, file_search_call items on Responses. The tool declaration is not a call. Third, model usage, where input has to account for retrieved chunks, not only the short citations in the answer. Rates follow the pricing page. This page was checked on 23 Oct 2026.
Funding the OpenAI account happens before those three debits. Moving stablecoins on-chain into an asset you can top up with does not fold daily storage into tokens, does not make an idle day free, and does not let max_num_results offset the call. When you need that conversion, use non-custodial AllSwap, which does not require an account. A completed swap only shows that the asset changed hands. If the vector store is still there, storage past the free gigabyte still shows up by the day.