Quickstart

Make a first call, then a correct integration

Five minutes gets you a first answer. The rest of this page is the difference between that and an integration you can put in front of a buyer: show the safety flags and the disclaimer, say “we do not know” when we do not, and stop showing an item once it is withdrawn.

These calls will work when the sandbox opens. Until then they show the shape of a request and the answer you will get. No key is needed for these calls.

1. Search by part number

Start with a part number from any brand. Search returns candidate items, not equivalences, and says how each was found in identified_by. exact_code means a mapped part number matched.

curl: search for a part number
curl -s "https://api.interchangeparts.com.au/v1/search?q=ALDC200C"
JavaScript (fetch): search for a part number
const response = await fetch("https://api.interchangeparts.com.au/v1/search?q=ALDC200C");
const body = await response.json();
console.log(response.status, body);
Python (requests): search for a part number
import requests

response = requests.get(
    "https://api.interchangeparts.com.au/v1/search",
    params={
        "q": "ALDC200C",
    },
)
print(response.status_code, response.json())
Example answer: one item identified
{
  "meta": {
    "api_version": "v1",
    "data_set": "sandbox"
  },
  "query": "ALDC200C",
  "status": "matched",
  "results": [
    {
      "ix_id": "IX-CAM-C-200-AL",
      "name": "Camlock Type C, 2\" (50 mm), aluminium",
      "identified_by": "exact_code",
      "matched_on": {
        "brand": "Dixon",
        "part_number": "ALDC200C"
      },
      "confidence": "verified",
      "safety_flags": []
    }
  ],
  "usage": {
    "attribution": "Source: Interchange (interchangeparts.com.au)",
    "disclaimer": "Cross-reference only. Check the manufacturer's current specification, rating and media compatibility before use."
  }
}

2. Get the equivalents

Take the ix_id from the result and ask for its equivalents. Equivalents are sorted by brand, A to Z. Keep that order. Add include_near=true to also get near matches, which are different items and are listed apart.

curl: equivalents of an item
curl -s "https://api.interchangeparts.com.au/v1/items/IX-CAM-C-200-AL/equivalents"
JavaScript (fetch): equivalents of an item
const response = await fetch("https://api.interchangeparts.com.au/v1/items/IX-CAM-C-200-AL/equivalents");
const body = await response.json();
console.log(response.status, body);
Python (requests): equivalents of an item
import requests

response = requests.get("https://api.interchangeparts.com.au/v1/items/IX-CAM-C-200-AL/equivalents")
print(response.status_code, response.json())
Example answer
{
  "meta": {
    "api_version": "v1",
    "data_set": "sandbox"
  },
  "ix_id": "IX-CAM-C-200-AL",
  "name": "Camlock Type C, 2\" (50 mm), aluminium",
  "status": "matched",
  "equivalents": [
    {
      "brand": "Alfagomma",
      "part_number": "CC-200-AL",
      "confidence": "verified",
      "reviewed": "2026-10-28",
      "evidence": "standard"
    },
    {
      "brand": "Dixon",
      "part_number": "ALDC200C",
      "confidence": "verified",
      "reviewed": "2026-10-28",
      "evidence": "standard"
    }
  ],
  "near_matches": [
    {
      "ix_id": "IX-CAM-C-200-SS6",
      "name": "Camlock Type C, 2\" (50 mm), 316 stainless",
      "same_fit": true,
      "differences": [
        {
          "attribute": "bodyMaterial",
          "this_value": "aluminium",
          "other_value": "stainless-316"
        }
      ]
    }
  ],
  "safety_flags": [],
  "suppliers_url": "https://interchangeparts.com.au/items/IX-CAM-C-200-AL#suppliers",
  "usage": {
    "attribution": "Source: Interchange (interchangeparts.com.au)",
    "disclaimer": "Cross-reference only. Check the manufacturer's current specification, rating and media compatibility before use."
  }
}

3. Show the safety flags and the disclaimer

This is the step a quick demo skips. Every answer carries usage.disclaimer, and every object that names an item carries safety_flags, on search results and candidates as well as on the equivalents answer. If a person sees the result, they see both. Show a flag’s message as written, and write its severity as a word. An empty list means none is known, not that the part is right for the job. Check meta.data_set too: sandbox means the data is illustrative.

The safety flags recipe shows this for screens, spreadsheets and assistants.

4. Handle no_verified_match

When nothing reviewed matches, status is no_verified_match, with a reason and an empty list. Tell the person Interchange has no verified match. Do not offer the nearest part, and do not say no equivalent exists: we do not know.

Example answer: nothing reviewed matches
{
  "meta": {
    "api_version": "v1",
    "data_set": "sandbox"
  },
  "query": "ZZ-9999",
  "status": "no_verified_match",
  "reason": "No reviewed item has this part number or description.",
  "results": [],
  "usage": {
    "attribution": "Source: Interchange (interchangeparts.com.au)",
    "disclaimer": "Cross-reference only. Check the manufacturer's current specification, rating and media compatibility before use."
  }
}

5. Handle 410 Gone

A withdrawn item answers 410 with the content type application/problem+json. It was withdrawn, usually because its mapping was wrong or unsafe. Stop showing it. If replaced_by is present, look that item up instead. A 404 is a different thing: that ID never existed.

Example answer: a withdrawn item
{
  "type": "https://interchangeparts.com.au/problems/withdrawn",
  "title": "Item withdrawn",
  "status": 410,
  "code": "withdrawn",
  "detail": "This item was withdrawn after a correction.",
  "replaced_by": "IX-CAM-C-200-AL",
  "request_id": "req_7c1f3b"
}

A retired item is not withdrawn: it still resolves and points to its successor. See handle a retired IX ID.

6. Put it together

This Node program does steps 1 to 5: it searches, accepts only a single exact part-number match, fetches the equivalents, merges the safety flags from both answers, and returns a plain result for each way it can end. It handles 429 by reporting it; wait for Retry-After before you try again.

JavaScript: a complete lookup
const BASE = "https://api.interchangeparts.com.au";

async function call(path) {
  const response = await fetch(BASE + path, { headers: { Accept: "application/json" } });
  return { status: response.status, body: await response.json(), requestId: response.headers.get("Interchange-Request-Id") };
}

// Flags can arrive on a search result, on a candidate and on the equivalents answer. Collect them all, once each.
function collectFlags(...lists) {
  const byCode = new Map();
  for (const flag of lists.flat()) byCode.set(flag.code, flag);
  return [...byCode.values()];
}

export async function lookUp(partNumber) {
  const search = await call("/v1/search?q=" + encodeURIComponent(partNumber));
  if (search.status === 429) throw new Error("Rate limited. Retry after the Retry-After header. Request " + search.requestId);
  if (search.status !== 200) throw new Error(search.body.code + " (request " + search.requestId + ")");

  // We do not know. That is not the same as "no equivalent exists", so say exactly that and stop.
  if (search.body.status === "no_verified_match") {
    return { kind: "unknown", reason: search.body.reason, disclaimer: search.body.usage.disclaimer };
  }

  // Only a mapped part number identifies an item on its own. Anything weaker is for a person to confirm.
  const exact = search.body.results.filter((r) => r.identified_by === "exact_code");
  if (exact.length !== 1) {
    return { kind: "confirm", candidates: search.body.results, disclaimer: search.body.usage.disclaimer };
  }
  const item = exact[0];

  const equivalents = await call("/v1/items/" + encodeURIComponent(item.ix_id) + "/equivalents");
  if (equivalents.status === 410) {
    // Withdrawn, usually because the mapping was wrong. Never show it. replaced_by names the correction, if there is one.
    return { kind: "withdrawn", ixId: item.ix_id, replacedBy: equivalents.body.replaced_by ?? null };
  }
  if (equivalents.status !== 200) throw new Error(equivalents.body.code + " (request " + equivalents.requestId + ")");

  const answer = equivalents.body;
  if (answer.status === "no_verified_match") {
    return { kind: "unknown", reason: answer.reason, disclaimer: answer.usage.disclaimer };
  }
  return {
    kind: "matched",
    ixId: answer.ix_id,
    name: answer.name,
    equivalents: answer.equivalents, // already sorted by brand, A to Z. Keep that order.
    safetyFlags: collectFlags(item.safety_flags, answer.safety_flags),
    disclaimer: answer.usage.disclaimer,
    attribution: answer.usage.attribution,
    dataSet: answer.meta.data_set, // "sandbox" means illustrative: do not rely on it for a purchase
  };
}

const result = await lookUp("ALDC200C");
console.log(result);

Next