> ## Documentation Index
> Fetch the complete documentation index at: https://docs.partfinder.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> The PartFinder API is served at https://api.partfinder.dev. Authenticate with `Authorization: Bearer $PARTFINDER_API_KEY`; create an account at https://console.partfinder.dev/sign-up and pick pay as you go or a monthly or yearly plan (see https://partfinder.dev/pricing), then create a key. Pay as you go starts with 100 free credits, once per person and per company.
> Install the PartFinder agent skill with `npx skills add https://docs.partfinder.dev` (skill file: https://docs.partfinder.dev/skill.md).
> The OpenAPI document at https://api.partfinder.dev/v1/openapi.json is the source of truth for request and response schemas.
> What each call costs and current plans: https://api.partfinder.dev/llms.txt.

# Use PartFinder with OpenAI tool calling

> Give a model on the OpenAI Responses API the PartFinder API as function tools built from the OpenAPI document.

This page gives a model on the OpenAI Responses API the PartFinder API as function tools. Your code runs each function call and sends the result back until the model answers.

## Install

```bash theme={null}
pip install openai requests   # Python
npm install openai               # JavaScript
export OPENAI_API_KEY="..."
export PARTFINDER_API_KEY="ak_..."
```

Save [`partfinder_tools.py` or `partfinder-tools.mjs`](https://docs.partfinder.dev/ai-agent-integration#build-the-tools-from-the-openapi-document)
next to your code. It builds the tools from the [OpenAPI document](https://api.partfinder.dev/v1/openapi.json)
and makes each call with the key from `PARTFINDER_API_KEY`.

## Give the model the tools

```python Python theme={null}
import json

from openai import OpenAI

from partfinder_tools import call_tool, operations

client = OpenAI()
model = "gpt-6-astra"

tools = [
    {
        "type": "function",
        "name": op["name"],
        "description": op["description"],
        "parameters": op["parameters"],
        "strict": False,
    }
    for op in operations
]

input_list = [{"role": "user", "content": "Is my PartFinder API key working?"}]
response = client.responses.create(model=model, tools=tools, input=input_list)

while any(item.type == "function_call" for item in response.output):
    input_list += response.output
    for item in response.output:
        if item.type != "function_call":
            continue
        input_list.append({
            "type": "function_call_output",
            "call_id": item.call_id,
            "output": call_tool(item.name, json.loads(item.arguments)),
        })
    response = client.responses.create(model=model, tools=tools, input=input_list)

print(response.output_text)
```

```javascript JavaScript theme={null}
import OpenAI from "openai";
import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";
import { operations, callTool } from "./partfinder-tools.mjs";

const openai = new OpenAI();
const model = "gpt-6-astra";

const tools = operations.map((op) => ({
  type: "function",
  name: op.name,
  description: op.description,
  parameters: op.parameters,
  strict: false,
}));

const input = [{ role: "user", content: "Is my PartFinder API key working?" }];
let response = await openai.responses.create({ model, tools, input });

while (response.output.some((item) => item.type === "function_call")) {
  input.push(...toResponseInputItems(response.output));
  for (const item of response.output) {
    if (item.type !== "function_call") continue;
    input.push({
      type: "function_call_output",
      call_id: item.call_id,
      output: await callTool(item.name, JSON.parse(item.arguments)),
    });
  }
  response = await openai.responses.create({ model, tools, input });
}

console.log(response.output_text);
```

`strict` set to false keeps the operations' optional parameters optional. The loop ends when a response has no `function_call` item, and `output_text` is the model's answer. Save it as `agent.py` or `agent.mjs` next to the tools file.

## Jobs and refusals

`searchParts`, `compareParts` and `analyzeBom` start a job. `call_tool` (`callTool`) waits for the job and returns the
finished result, so the model does not need to poll. A refused call returns the API's JSON with its `error` code and
`summary`, and the model reads it like any other result. See [AI agent integration](https://docs.partfinder.dev/ai-agent-integration.md)
for the rest of the rules.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.