Partner API

Live inventory and Certificates of Analysis from a real manufacturer; holds and orders for fulfilment partners. Contract: /openapi.json · For agents: /llms.txt

Authentication

Authorization: Bearer pk_XXXXX:sk_YYYYYYYY

Keys are issued by the manufacturer’s operator, carry scopes, and may be bound to one brand. A sandbox key behaves identically but touches only rehearsal stock that can never ship.

Versioning

Pharmagistic-Version: 2026-09-06

Optional; omit it for the current version. A date newer than this deployment is a 400 unsupported_version. Dates are added, never rewritten: a shape that exists on a date keeps that shape on that date.

Start here: inventory + COA, read only

Most partners begin with the read-only feed: show our live availability and our Certificates of Analysis on your own site. No pricing (prices are yours), no holds, no orders. A read-only key carries atp.products, atp.inventory and atp.check; every other endpoint answers 403.

  1. GET /api/v1/products — every SKU you may sell, with availability.
  2. GET /api/v1/inventory?sku=… — the live count for one SKU.
  3. The COA feed below — the certificate for each product.

Certificates of Analysis

The COA feed is served by our storefront platform and accepts the same key:

GET https://usamadepeptides.us/api/partner/v1/coa
GET https://usamadepeptides.us/api/partner/v1/coa/lot/{lot}

Query: ?status=current|archived|retired|all (default current), ?product=<slug> (repeatable), ?updated_since=<ISO 8601> for incremental sync, ?format=json|csv, ?limit=1..500&cursor=. Each record carries product{slug,name}, batch_number, vial_size, tested_on, lab_name, purity_pct, status, certificate_url (PDF), verify_url and updated_at. A retired lot is a tombstone with an empty certificate_url: take it down. Match COAs to products by product.slug; your operator sends the slug ↔ SKU map with your key. Anyone can verify one lot without a key at https://usamadepeptides.us/coa/lookup?lot=<LOT>.

Go-live

Build against a sandbox key first. When the checks below pass, tell your operator; we read your sandbox traffic, then issue a production key bound to your brand and revoke the sandbox key 30 days later.

The flow (fulfilment keys only)

  1. Reserve the units. You get a reservation_token, good for 30 minutes.
  2. Charge the customer — your gateway, your rules.
  3. Place or consume. POST /api/v1/orders hands us the order and we ship it; POST /api/v1/consume keeps the units and you ship them.

Reserve before you charge. /check is advisory and can be stale; the reserve is the only answer that holds physical vials. A short reserve means do not take the money.

Endpoints

POST /api/v1/checkAvailable-to-promise for one or more SKUs (no hold)
POST /api/v1/reserveHold inventory (brand pool first, then shared per access)
POST /api/v1/releaseRelease a hold
POST /api/v1/consumeConsume a hold WITHOUT creating an OMS order
POST /api/v1/consume/reverseGive back the units a consume took, when the sale is reversed
GET /api/v1/inventoryATP for one SKU by brand plus totals
GET /api/v1/productsEvery sellable SKU, with availability for this key
POST /api/v1/ordersPlace the pickable OMS order from a hold (one transaction)
GET /api/v1/orders/{ref}An order this key placed, by order id or Idempotency-Key
POST /api/v1/orders/{ref}/cancelCancel an order this key placed, before it is picked
POST /api/v1/shipments/combineShip several of this key's orders in one box (combined shipments)
POST /api/v1/keys/introspectIs this token a live OMS key, and what may it do?
GET /api/v1/shipmentsThis key's brand's ShipStation queue, by modification time
POST /api/v1/reserve-cachePush the console's prepaid-reserve mirror for one brand
POST /api/v1/confirm deprecatedLegacy: place an OMS order from a hold (use POST /api/v1/orders)

Errors

{ "error": { "code": "reservation_gone", "message": "..." } }

Codes are stable strings. Match on code, never on message.

no_inventoryNot enough stock for those lines. Do not charge.
reservation_goneThe hold is over (expired or released). Reserve again.
reservation_expiredThe hold aged out of its 30-minute window.
reservation_usedAlready consumed or placed. You have been served once already.
idempotency_mismatchThat Idempotency-Key was used with a different hold.
order_not_cancellableThe order is picked or shipped. It needs a return authorization.
brand_mismatchThis key may only act for its own brand.
rate_limited429. Retry-After carries the seconds.
unsupported_versionThe version date is newer than this deployment.

Webhooks

We send order.shipped and order.held to the URL you register, signed in Svix format: svix-id, svix-timestamp (Unix seconds) and svix-signature = v1,<base64 HMAC-SHA256 of "id.timestamp.body">keyed by your whsec_ secret.

Sandbox

A sandbox key draws on the SANDBOX brand: fake units, no shared-pool access, nothing that can ship. Same endpoints, same errors, same shapes. Rehearse reserve → charge → order there before you touch real stock.

Status

Beta. The endpoints and error codes on this page are stable and versioned by date. A breaking change gets a new version date and ninety days of overlap, and the old date keeps working for that whole window.