XrefBase

Developers · API v1

The cross-reference, over HTTP.

Send a manufacturer part number; get back the answer the XrefBase lookup gives, as JSON — the same six buckets, the same public sources, and the page to cite. No key, no account.

Who it is for

Procurement, PLM and BOM software that needs the next part number without a person typing the current one into a website. A cross-reference check belongs inside the tool where the part is already on screen: when a line goes on allocation, when an end-of-life notice lands, when a component engineer reviews a supplier's substitution.

It answers one question — what else will work, and on whose authority — and nothing about stock, price or datasheets. Every relationship it returns carries the public document it rests on.

Quickstart

One lookup is a GET. The part number here is a real one: TE retired it and named its successor in a product change notice.

curl
curl "https://www.xrefbase.com/api/v1/alternatives?mpn=1-968880-3"
JavaScript · fetch
const url = new URL("/api/v1/alternatives", "https://www.xrefbase.com");
url.searchParams.set("mpn", "1-968880-3");
// url.searchParams.set("manufacturer", "TE Connectivity");

const response = await fetch(url);
if (!response.ok) {
  // 400: fix the request. 503: nobody checked —
  // retry later; never record it as "no alternatives".
  throw new Error((await response.json()).error.message);
}

const { result } = await response.json();
if (result.ambiguous) {
  // More than one manufacturer carries this number.
  // Ask which one (result.candidates), then look up
  // again with it. Do not pick one yourself.
} else if (!result.matched) {
  // Not assessed. Show result.message; never say
  // "no alternatives".
} else {
  // The only bucket that asserts substitutability:
  console.log(result.verified_replacements);
  // Cite this page wherever the answer is shown:
  console.log(result.matched_part.url);
}
Response · recorded 2026-09-26
{
  "api_version": "1",
  "retrieved_at": "2026-09-26T09:00:00.000Z",
  "attribution": {
    "source": "XrefBase",
    "url": "https://www.xrefbase.com",
    "cite": "When result.matched is true, link every answer you display to result.matched_part.url: the XrefBase page for that part, which shows each relationship with its public source. An unmatched or ambiguous answer has no part page; link it to the lookup instead, https://www.xrefbase.com/?mpn=<the part number you asked about>.",
    "documentation": "https://www.xrefbase.com/developers"
  },
  "result": {
    "query": {
      "part_number": "1-968880-3",
      "manufacturer": null
    },
    "matched": true,
    "variants": [],
    "ambiguous": false,
    "mates_with": [],
    "matched_via": "mpn",
    "same_series": [],
    "matched_part": {
      "mpn": "1-968880-3",
      "url": "https://xrefbase.com/part/te-connectivity/1-968880-3",
      "series": "AMP MCP 2.8",
      "category": "Terminals & Contacts",
      "manufacturer": "TE Connectivity",
      "also_known_as": []
    },
    "people_waiting": 0,
    "verified_replacements": [
      {
        "mpn": "1-2141857-3",
        "url": "https://www.xrefbase.com/part/te-connectivity/1-2141857-3",
        "sources": [
          {
            "url": "https://mm.digikey.com/Volume0/opasdata/d220001/medias/docus/2859/E-20-012094.pdf",
            "title": "TE E-20-012094",
            "locator": "Description of Changes: 1-968880-3 obsolete and replaced by 1-2141857-3. (The PCN's replacement table lists the part as discontinued and leaves its Substitute Part Number column empty; the pairing is stated in the narrative.)",
            "retrieved_at": "2026-09-05T12:03:58.375839+00:00"
          }
        ],
        "evidence": "Description of Changes: 1-968880-3 obsolete and replaced by 1-2141857-3. (The PCN's replacement table lists the part as discontinued and leaves its Substitute Part Number column empty; the pairing is stated in the narrative.)",
        "relation": "supersedes",
        "confidence": "high",
        "source_url": "https://mm.digikey.com/Volume0/opasdata/d220001/medias/docus/2859/E-20-012094.pdf",
        "manufacturer": "TE Connectivity"
      }
    ],
    "functional_equivalents": [],
    "superseded_predecessors": []
  }
}

result is the database's answer, passed through verbatim — key order included. result.matched_part.url is the page to cite: it lists every relationship with its public source and always shows the current state, so a reader can check an answer your system cached months ago.

A single lookup puts the part number in the URL, where access logs keep it — yours, any proxy's, the CDN's. If the list of parts you are asking about is itself sensitive, use the batch endpoint: it is a POST for that reason.

The bucket contract

A matched answer has six arrays, often empty. The bucket a part arrives in is the claim XrefBase makes about it.

FieldClaimWhat it means
verified_replacementsPublished replacementsAsserts substitutionThe only results asserting a replacement relationship. Confirm application-specific fit before use.
functional_equivalentsFunctional equivalentsNot a substituteSimilar function, not a confirmed drop-in. Engineering review is required before substitution.
superseded_predecessorsSuperseded predecessorsNot a substituteProduct history, shown for context only — not an alternative to this part.
same_seriesSame seriesNot a substituteSame family, different configuration. Family navigation, not a substitution claim.
variantsVariantsNot a substituteThe same part in a different keying, colour or packaging suffix.
mates_withMating counterpartsNot a substituteWhat this component plugs into. These are never substitutes for it.

Inside verified_replacements, relation says whose claim it is: supersedes is a supersession — the manufacturer replaced the part — and drop_in is a drop-in XrefBase has verified. Different claims by different authorities; show which. relation refines a claim within its bucket and never moves a part to another.

An empty bucket means nothing is recorded, not that nothing exists.

Integration rules

Break one of these and your product says something XrefBase does not.

  1. Never flatten the buckets. Not into one list, one table column, or one count called “alternatives” or “replacements”. Flattening is a correctness bug, not a presentation choice: it turns a mating counterpart into a suggested substitute.
  2. Never present context as an alternative. Only verified_replacements asserts substitutability. functional_equivalents need engineering review before anyone substitutes. superseded_predecessors, same_series and variants are history and family navigation. mates_with is what the part plugs into — the one part guaranteed not to substitute for it.
  3. Always cite matched_part.url. Link every matched answer you show to it, so a reader can see the source behind each relationship and whether it still stands. An unmatched or ambiguous answer has no part page — link it to the lookup, /?mpn= the number you asked about.
  4. Unmatched means not assessed. matched: false with ambiguous: false means XrefBase does not carry the part, or did not recognise the manufacturer you gave — message says which. Neither is a finding that no alternative exists, and neither may be shown as one. If you supplied a manufacturer, retry without it before concluding anything.
  5. Ambiguous means ask. ambiguous: true comes with candidates and no buckets. Ask the user, or your own part master, which manufacturer is meant and look up again with it. Do not take the first candidate.
  6. An error is not an answer. A 503, or a batch entry with status: "error", means nobody checked. Say you could not check, retry later, and never store it as an empty result.
  7. Ignore fields you do not recognise. Fields may be added within v1 — the url on every related part arrived that way. None is removed or renamed without a new version path.

Status and errors

Matched, not assessed and ambiguous are all answers, so all three are a 200. Read result.matched and result.ambiguous, not the status code.

SituationStatusYou getShow
Part identified200matched: true, matched_part, the six bucketsEach non-empty bucket under its own heading, citing matched_part.url
Not in the catalogue200matched: false, ambiguous: false, messageNot assessed yet — never “no alternatives”
Manufacturer not recognised200The same, with a message naming the manufacturerNothing yet — retry without manufacturer
More than one manufacturer200ambiguous: true, candidates, no bucketsA choice of manufacturer
Invalid input400error.code: invalid_input and error.fieldNothing — fix the request
Lookup failed or timed out503lookup_unavailable or lookup_timeout, never cachedThat you could not check — retry later
Error body
{
  "api_version": "1",
  "error": {
    "code": "invalid_input",
    "message": "mpn is required.",
    "field": "mpn"
  }
}

mpn is required; manufacturer is optional. Both are trimmed and limited to 80 characters. If a parameter is repeated, the first value is used — the same rule the lookup page follows.

Every response carries Access-Control-Allow-Origin: *, so the API can be called from a browser. Answers are Cache-Control: public, s-maxage=300, stale-while-revalidate=3600; errors and batches are no-store. retrieved_at is when the answer was read from the database, and a cached response keeps its original time.

Batch

Up to 50 lines of a bill of materials in one request.

The part numbers travel in the request body, so they never sit in a URL, a browser history or an access log. XrefBase neither logs nor stores them.

curl
curl -X POST "https://www.xrefbase.com/api/v1/alternatives/batch" \
  -H "Content-Type: application/json" \
  -d '{"items": [
        {"mpn": "1-968880-3"},
        {"mpn": "DT04-3P", "manufacturer": "Deutsch"},
        {"mpn": "ZAG 16"}
      ]}'
Response · shape, abridged
{
  "api_version": "1",
  "retrieved_at": "2026-09-26T09:00:00.000Z",
  "attribution": { … },
  "results": [
    { "input": { "mpn": "1-968880-3" },
      "status": "ok",
      "result": { "matched": true, … } },
    { "input": { "mpn": "DT04-3P", "manufacturer": "Deutsch" },
      "status": "ok",
      "result": { "matched": true, "mates_with": [ … ], … } },
    { "input": { "mpn": "ZAG 16" },
      "status": "ok",
      "result": { "matched": false, "ambiguous": true,
                  "candidates": [ … ], … } }
  ]
}
  • One entry per item, in input order. input echoes the item exactly as you sent it.
  • status: "ok" carries result — the same object a single lookup returns, with the same three shapes and the same rules. status: "error" carries error: invalid_input for a malformed line, lookup_unavailable or lookup_timeout when nobody checked.
  • One bad line never fails the batch, so a well-formed request is always a 200. Check status on every entry.
  • 1–50 items and at most 64 KiB per body, looked up 6 at a time with a 5-second limit per item. Over a limit is a 413 (too_many_items, body_too_large); a body that is not JSON or has no items is a 400 (invalid_body).

Fair use

There are no API keys and no published rate limit yet. That is not a promise of unlimited capacity. What is enforced today is what this page lists: 50 items and 64 KiB per batch, 6 lookups at a time within one.

Single lookups are cached at the edge for five minutes and may be served up to an hour stale while the cache refreshes, so repeating one is cheap. Be proportionate beyond that: keep answers on your side, send a bill of materials as a batch rather than fifty single requests, and back off when you get a 503.

The full contract, with every schema and the bucket semantics in its descriptions, is the OpenAPI 3.1 document.