Skip to main content
For developers building PartFinder into their own product’s assistant. Using an existing agent such as Claude Code? See MCP server and Agent skills. The API is built for a model to read. Every score carries its scale, direction and a sentence; every measure carries its unit; unknown values are explicit nulls with a reason; and every response, errors included, carries a summary line your agent can relay verbatim.

Build the tools from the OpenAPI document

Generate your tool definitions from our OpenAPI document, https://api.partfinder.dev/v1/openapi.json. It always matches what is live. A hand-written definition drifts the first time we add a parameter, and you will not find out until a call fails. partfinder_tools.py (Python) and partfinder-tools.mjs (JavaScript) read the OpenAPI document and turn each operation into a tool: its operation id as the name, its description, and one JSON Schema for its parameters and request body. Their call_tool / callTool makes the call a tool call names, with the key from PARTFINDER_API_KEY. When a job answers 202, it reads the job every Retry-After seconds until it is no longer processing, so the model gets the finished result. Key and webhook operations, header parameters and the file upload are left out of the tools.
Each of these pages passes operations and call_tool (callTool in JavaScript) to one SDK:

Handling the response

Pass the JSON back to the model as the tool result. It needs no preprocessing. A few things worth handling in code or in your prompt rather than leaving to the model: An error is an answer, not an outage. A 422 or 404 carries a summary explaining what was wrong, and often carries did_you_mean: parts of the kind you described on a 422, and the listed part numbers your input is a prefix of on a 404. Feed that back like any other result. A null is information. "lead_time_min": { "value": null, "reason": "The middle half of quoted lead times is a single figure, so there is no range." } means we checked. So does "manufacturing_country": null, and when that is null the geography driver has no band ("tier": null) and its interpretation says why. A model that fills a null in itself will present a guess as a finding. Relay disruption items in the order given. disruption_events lists what most affects the part’s score, strongest first. An item’s severity is how serious the event is in itself, not its effect on this part, so a high item can sit below a medium one, and a part can carry high items beside a low disruption_exposure. Tell your model not to re-rank the list by severity. Pass country when you know where the buyer is. Send it as a two-letter code (SG, not Singapore) when the user says where they are, or when your product already knows it. The answer to “where can I buy this near me” is then supply.nearby.summary, a sentence you can relay as it is. The score does not change with it.

A worked exchange

User: “Can I still get TPS5433?” Your agent calls researchPart({ mpn: "TPS5433" }) and gets:
Agent: relays the summary, offers the three part numbers, and calls again once the user picks one. Nothing was invented, and the user got further than “not found”.

Several parts in one question

For a few parts, ask for each one separately. Most providers emit parallel tool calls in a single round, so three parts cost roughly the wall-clock of the slowest one. Each call is independent, and a part that fails does not affect the others. For a whole list, submit it as a BOM with POST /v1/bom (see BOM Analysis): one call, every line scored against the rest of the BOM.

Alternates as a tool

For “what can replace this part?”, call getAlternates (GET /v1/alternates) and relay its summary. Tell your model to present the results as candidates to check against the datasheets, never as confirmed drop-in replacements. See Find alternate parts.

Search as a tool

For “find me a part like this” or “what is there for a 3A buck converter?”, call searchParts (POST /v1/search) with the user’s words as query. It is asynchronous like a BOM: it answers 202 with the search’s id and Retry-After: 35. Poll getSearch from your code until status is no longer processing, then hand the model the result (see the polling note under BOMs below). Relay the summary, and present the rows as candidates to check against their datasheets. See Search for parts.

Compare as a tool

For “is this part a match for that one?” or “how do these three differ?”, call compareParts (POST /v1/compare). When the user names the parts, send them all in parts, the one to compare against first; send mpn alone only to compare one part with its alternates. It is asynchronous like a search: poll getComparison from your code until status is no longer processing, then hand the model the result. Relay the summary, and tell your model a verdict compares what the datasheets state, not a qualification. See Compare parts.

BOMs as a tool

Four operations turn a parts list into a risk report: analyzeBom (POST /v1/bom), getBom, listBoms and deleteBom. Generated from our OpenAPI document, they arrive with their parameters and request body already described. Submitting is asynchronous. analyzeBom answers 202 at once with the BOM’s id, a Location header pointing at the report, and Retry-After: 5. Poll from your code, not from the model: a model has no clock, so it calls getBom back to back and spends turns. Call getBom with that id every Retry-After seconds until bom.status is complete, then hand the model the report. While it is processing, the report is partial and its summary says how far along it is, which you can show as progress. Every BOM reaches complete: lines that could not be analyzed come back with status: unresolved rather than holding the BOM open. From the BOM to a part. When any line is high or critical, the report’s summary ends by saying so and naming GET /v1/parts. That is the next call: research those lines with researchPart for their alternates, datasheet and a plain summary of the figures behind their risk. Ask before deleting. deleteBom removes the BOM and its report for good. Tell your model to confirm with the user before calling it. Files stay in your code. A model cannot attach a file to a tool call. When your user uploads a CSV or XLSX, send it from your own code to POST /v1/bom/upload (multipart, field file), poll getBom from your code as above, then hand the model the report. Pages: pass the cursor back unchanged. listBoms returns up to 50 BOMs and a next_cursor when there are more. The next page is the same call with that cursor, copied exactly. Keep the tool calls and their results in the conversation between turns, not only the text: a model asked for “the next page” without the previous result in front of it will make up a cursor, and a cursor we did not issue is refused with 400.

Timeouts and repeats

A part can take tens of seconds the first time it is requested, and is fast after that. Set your client timeout to at least 90 seconds, and do not retry on timeout alone: a second call often returns quickly. A 429 rate_limited means your organization has used its calls for this minute or this day (see Errors). Handle it in your code, not in the model: wait the seconds in the Retry-After header, then retry. If the wait is long (the daily limit), relay the summary instead of waiting. To avoid the 429 altogether, read X-RateLimit-Remaining on each response and slow down as it approaches zero. Each BOM poll counts toward the limit, and so does every retry of a failed call: back off between retries of a 502 or 503 rather than retrying at once. Retry 503 verification_unavailable with backoff, and do not let your agent report it as the part not existing: that answer is 404. Do not retry 404 or 422; they are answers.

Idempotency keys belong to your code, not the model

POST /v1/bom, POST /v1/bom/upload, POST /v1/search and POST /v1/compare accept an optional Idempotency-Key header so a retried submission does not create a second BOM, search or comparison. A key is recognised only from the API key that sent it. Without the header everything works; a retried submission simply creates a second BOM, search or comparison. Set the header in the code that turns your model’s tool call into an HTTP request: generate a new value (a UUID) for each tool call, and send the same value again only when that code retries the same request after a timeout. Do not expose the header to the model as a tool argument, and do not derive it from the conversation. A model that reuses one value for two different BOMs gets the first BOM back for the second, because the body is not compared. If you generate your tool from our OpenAPI document, drop header parameters from what the model sees.

Part Research

What the response contains, field by field.

BOM Analysis

Submitting a BOM, polling it and reading the report.

Errors

Every status code and how to handle it.