<!-- title: API Reference | order: 9 | summary: Every 2026-01 wire method with request/response/error schemas and a runnable curl, plus the proposed extensions. -->
<!-- GENERATED by scripts/gen-api-reference.ts from docs/partly-openapi.json — do NOT edit by hand; run `pnpm codegen`. -->

# API Reference

Generated from the published OpenAPI spec — the **14 wire methods** of the public `2026-01` Integrations API. This page is a per-method overview; [`/openapi.json`](/openapi.json) is the full machine-readable contract (every schema resolved), and the better source for generating a typed client.

Every call is `POST <base>/api/2026-01/<dotted.method>` with a JSON body. See [Authentication](./authentication.md) for the two required headers and [Errors](./errors.md) for the coded error model. Examples use the pre-loaded demo credentials; set the base URL once, and prepend `-H 'x-partifact-tenant: <name>'` for a private, isolated sandbox (see [Quickstart](./quickstart.md)).

```bash
BASE=https://partifact-mock-rails.thanhvuttv.workers.dev
```

> **Wire-truth (D52).** The basket response (`repairer.jobs.baskets.latest.get` → `BasketsLatestGetResponseV1`, `OfferV1`) carries **no `currency` field**. Currency is a procurement-level concept — `currency_code` on the procurement and the invoice, never on a basket offer.

> **Bare-string errors (D24).** Most methods return type-tagged error bodies (`{"type":"not_found"}`). The one exception is `repairer.jobs.parts.insert`, whose error variants are **bare JSON strings** (`"not_found"`). See [Errors](./errors.md).

---

## Wire methods (2026-01)

### `businesses.list`

Lists the sub-businesses of the organization that the integration belongs to.

| | |
|---|---|
| **Request** | `BusinessesListRequestV1` — required: _none_ |
| **Response** | `BusinessesListResponseV1` — `items`: `BusinessV1`[] |
| **Errors** | `unauthorized`, `forbidden` |

```bash
curl -sS -X POST "$BASE/api/2026-01/businesses.list" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{}'
```

### `integrations.insert`

Completes the integration installation and API key generation for a given install. The request must provide the client secret, client ID and the access code generated during the OAuth authorization process

| | |
|---|---|
| **Request** | `IntegrationsInstallRequestV1` — required: `access_code`, `client_id`, `client_secret` |
| **Response** | `IntegrationsInstallResponseV1` — `api_key`: `std.string.String`, `integration_id`: `uuid.Uuid` |
| **Errors** | `unauthorized`, `forbidden`, `integration_not_found`, `o_auth_not_supported_by_integration`, `invalid_client_secret`, `invalid_access_code` |

```bash
curl -sS -X POST "$BASE/api/2026-01/integrations.insert" \
  -H "Content-Type: application/json" \
  -d '{"access_code":"ac_demo_valid_15m","client_id":"partly_client_demo","client_secret":"secret_demo_8f3a"}'
```

### `repairer.jobs.baskets.latest.get`

Fetches the latest basket for a given repair job.

| | |
|---|---|
| **Request** | `BasketsLatestGetRequestV1` — required: `job_identity` |
| **Response** | `BasketsLatestGetResponseV1` — `offers`: `OfferV1`[], `suppliers`: `SupplierV1`[] |
| **Errors** | `unauthorized`, `forbidden`, `not_found`, `bad_request` |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.jobs.baskets.latest.get" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"job_identity":{"external":"CCC-2026-04817"}}'
```

### `repairer.jobs.get`

Fetches a repair job by ID, external ID, or siteID and job number

| | |
|---|---|
| **Request** | `_(inline)_` — required: `identity` |
| **Response** | `JobV1` — `claim_number`?: oneOf, `external_id`?: oneOf, `id`: `uuid.Uuid`, `images`: `ImageV1`[], `job_number`?: oneOf, `repairer_site_id`: `uuid.Uuid`, `vehicle`?: oneOf, `work_provider_id`?: oneOf |
| **Errors** | `unauthorized`, `forbidden`, `not_found` |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.jobs.get" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"identity":{"external":"CCC-2026-04817"}}'
```

### `repairer.jobs.insert`

Inserts a new repair job or updates an existing repair job.

| | |
|---|---|
| **Request** | `JobsInsertRequestV1` — required: `repairer_site_id`, `identity` |
| **Response** | `JobV1` — `claim_number`?: oneOf, `external_id`?: oneOf, `id`: `uuid.Uuid`, `images`: `ImageV1`[], `job_number`?: oneOf, `repairer_site_id`: `uuid.Uuid`, `vehicle`?: oneOf, `work_provider_id`?: oneOf |
| **Errors** | `unauthorized`, `forbidden`, `unprocessable`, `work_provider_not_found` |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.jobs.insert" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"identity":{"external":"CCC-2026-04817"},"repairer_site_id":"0b000000-0000-4000-8000-000000000001","work_provider_id":"0a000000-0000-4000-8000-000000000020"}'
```

### `repairer.jobs.parts.insert`

Inserts parts for a repair job.

| | |
|---|---|
| **Request** | `JobsPartsInsertRequestV1` — required: `job_identity`, `parts` |
| **Response** | `JobsPartsListResponseV1` — `items`: `PartV1`[] |
| **Errors** | `unauthorized`, `forbidden`, `not_found`, `unprocessable` — **bare JSON strings**, not `{type}` objects (D24) |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.jobs.parts.insert" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"job_identity":{"external":"CCC-2026-04817"},"parts":[{"description":"Front bumper cover assembly","quantity":1}]}'
```

### `repairer.jobs.parts.list`

Lists all parts for a repair job.

| | |
|---|---|
| **Request** | `JobsPartsListRequestV1` — required: `job_identity` |
| **Response** | `JobsPartsListResponseV1` — `items`: `PartV1`[] |
| **Errors** | `unauthorized`, `forbidden`, `not_found` |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.jobs.parts.list" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"job_identity":{"external":"CCC-2026-04817"}}'
```

### `repairer.procurements.get`

Fetch a procurement for a repairer by ID

| | |
|---|---|
| **Request** | `_(inline)_` — required: `identity` |
| **Response** | `procurements.v1.buyer.Procurement` — `created_at`: string, `currency_code`: oneOf, `id`: `uuid.Uuid`, `job_id`: `uuid.Uuid`, `reference`: oneOf, `source_items`: `procurements.v1.buyer.SourceItem`[], `supplier_business`: `procurements.v1.buyer.SupplierBusiness`, `supplier_organization`: `procurements.v1.buyer.SupplierOrganization`, `total_shipping_price`: oneOf, `updated_at`: string, `vehicle`: `procurements.v1.Vehicle` |
| **Errors** | `unauthorized`, `forbidden`, `not_found` |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.procurements.get" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"identity":{"id":"10000000-0000-4000-8000-000000000001"}}'
```

### `repairer.procurements.list`

List procurements for a repairer

| | |
|---|---|
| **Request** | `procurements.v1.repairer.ProcurementsListRequest` — required: `job_identity` |
| **Response** | `procurements.v1.buyer.ProcurementsListResponse` — `items`: `procurements.v1.buyer.Procurement`[] |
| **Errors** | `unauthorized`, `forbidden`, `not_found` |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.procurements.list" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"job_identity":{"external":"CCC-2026-04817"}}'
```

### `repairer.work-providers.list`

Fetches the list of work providers for a repairer.

| | |
|---|---|
| **Request** | `WorkProvidersListRequestV1` — required: _none_ |
| **Response** | `WorkProvidersListResponseV1` — `items`: `WorkProviderV1`[] |
| **Errors** | `unauthorized`, `forbidden` |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.work-providers.list" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{}'
```

### `supplier.procurements.confirm`

Transition a procurement to order confirmed

| | |
|---|---|
| **Request** | `_(inline)_` — required: `identity` |
| **Response** | `procurements.v1.supplier.Procurement` — `buyer_business`: `procurements.v1.supplier.BuyerBusiness`, `buyer_organization`: `procurements.v1.supplier.BuyerOrganization`, `buyer_shipping_address`: `procurements.v1.Address`, `created_at`: string, `currency_code`: oneOf, `id`: `uuid.Uuid`, `job_id`: `uuid.Uuid`, `reference`: oneOf, `source_items`: `procurements.v1.supplier.SourceItem`[], `total_shipping_price`: oneOf, `updated_at`: string, `vehicle`: `procurements.v1.Vehicle` |
| **Errors** | `unauthorized`, `forbidden`, `not_found` |

```bash
curl -sS -X POST "$BASE/api/2026-01/supplier.procurements.confirm" \
  -H "Authorization: Bearer partly_demo_supplier_8b4e2f1a6c0d3e9f7a25" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000002" \
  -H "Content-Type: application/json" \
  -d '{"identity":{"id":"10000000-0000-4000-8000-000000000001"}}'
```

### `supplier.procurements.get`

Fetch a procurement for a supplier by ID

| | |
|---|---|
| **Request** | `_(inline)_` — required: `identity` |
| **Response** | `procurements.v1.supplier.Procurement` — `buyer_business`: `procurements.v1.supplier.BuyerBusiness`, `buyer_organization`: `procurements.v1.supplier.BuyerOrganization`, `buyer_shipping_address`: `procurements.v1.Address`, `created_at`: string, `currency_code`: oneOf, `id`: `uuid.Uuid`, `job_id`: `uuid.Uuid`, `reference`: oneOf, `source_items`: `procurements.v1.supplier.SourceItem`[], `total_shipping_price`: oneOf, `updated_at`: string, `vehicle`: `procurements.v1.Vehicle` |
| **Errors** | `unauthorized`, `forbidden`, `not_found` |

```bash
curl -sS -X POST "$BASE/api/2026-01/supplier.procurements.get" \
  -H "Authorization: Bearer partly_demo_supplier_8b4e2f1a6c0d3e9f7a25" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000002" \
  -H "Content-Type: application/json" \
  -d '{"identity":{"id":"10000000-0000-4000-8000-000000000001"}}'
```

### `tier1.prepare`

Queue up a given vehicle VIN for future use in other services.

| | |
|---|---|
| **Request** | `Tier1PrepareRequestV1` — required: `identifiers` |
| **Response** | `Tier1PrepareResponseV1` — `invalid_identifiers`: `InvalidIdentifierV1`[] |
| **Errors** | `unauthorized` |

```bash
curl -sS -X POST "$BASE/api/2026-01/tier1.prepare" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"identifiers":[{"vin":"JTDBR32E730012345"}]}'
```

### `uploads.prepare`

Generate a pre-signed URL for uploading a file.

| | |
|---|---|
| **Request** | `UploadsPrepareRequestV1` — required: `file_name`, `media_type`, `type` |
| **Response** | `UploadsPrepareResponseV1` — `public_url`: oneOf, `upload_url`: `std.string.String` |
| **Errors** | `unauthorized`, `forbidden`, `unprocessable` |

```bash
curl -sS -X POST "$BASE/api/2026-01/uploads.prepare" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"file_name":"estimate.jpg","media_type":"image","type":"job_media"}'
```

---

## Proposed extensions (NOT in 2026-01)

These three methods are **not** part of the public `2026-01` contract and are **not** in [`/openapi.json`](/openapi.json). the upstream platform performs procurement-placement and invoice-reconciliation internally but exposes no public method; here they are reconstructed as a clearly-labelled proposed extension so the buyer loop is demonstrable end to end. Every extension response carries `x_extension: true`. See [Lifecycle](./lifecycle.md).

### `repairer.procurements.insert` _(MCP tool: `place_procurement` ⚠)_

> (Proposed extension beyond the public 2026-01 API — the public contract stops at `order_confirmed`; this completes the buyer loop.)

Creates a procurement in `order_requested` from selected basket offers and moves the chosen parts `estimated → ordered`. Its response carries `"x_extension": true`.

| | |
|---|---|
| **Request** | `job_identity` + `offer_selections[]` (each `{ sellable_id, supplier_business_id, job_part_ids, quantity }`) |
| **Response** | `RepairerProcurementsInsertResponseV1` (local schema; `x_extension: true`) |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.procurements.insert" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"job_identity":{"external":"CCC-2026-04817"},"offer_selections":[{"sellable_id":"0f000000-0000-4000-8000-000000000007","supplier_business_id":"0b000000-0000-4000-8000-000000000010","job_part_ids":["0e000000-0000-4000-8000-000000000004"],"quantity":1}]}'
```

### `repairer.procurements.invoices.list` _(MCP tool: `reconcile_invoice` ⚠)_

> (Proposed extension beyond the public 2026-01 API — the public contract stops at `order_confirmed`; this completes the buyer loop.)

Lists the reconciled invoices and credit notes for a procurement (or job). Invoices appear only after `order_confirmed`. Its response carries `"x_extension": true`.

| | |
|---|---|
| **Request** | exactly one selector — `procurement_identity` XOR `job_identity` |
| **Response** | `RepairerProcurementsInvoicesListResponseV1` (local schema; `x_extension: true`) |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.procurements.invoices.list" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"procurement_identity":{"id":"10000000-0000-4000-8000-000000000001"}}'
```

### `repairer.procurements.invoices.get`

> (Proposed extension beyond the public 2026-01 API — the public contract stops at `order_confirmed`; this completes the buyer loop.)

Fetches a single invoice or credit note by its own id (obtain the id from `repairer.procurements.invoices.list`). Its response carries `"x_extension": true`.

| | |
|---|---|
| **Request** | `identity` — `{ id: <invoice_id> }` |
| **Response** | `RepairerProcurementsInvoicesGetResponseV1` (local schema; `x_extension: true`) |

```bash
curl -sS -X POST "$BASE/api/2026-01/repairer.procurements.invoices.get" \
  -H "Authorization: Bearer partly_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
  -H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
  -H "Content-Type: application/json" \
  -d '{"identity":{"id":"<invoice_id from invoices.list>"}}'
```
