Skip to content
lensmount

Free JSON endpoint

Compatibility API

Every cell of the compatibility matrix is reachable as JSON. Pass a lens-side mount id and a body-side mount id, get feasibility, AF, IS, aperture-control, infinity-focus, adapter SKU list, plain-language caveats, and any image-circle mismatch back as a single response. No auth, no sign-up, no rate limit at low volume.

Endpoint

One read-only endpoint, GET only. Replace the two angle-bracketed placeholders with mount ids from the list below.

https://lensmount.hk2.ai/api/compat?lens=<mount-id>&body=<mount-id>

Example — Canon EF lens on a Canon RF body:

curl 'https://lensmount.hk2.ai/api/compat?lens=canon-ef&body=canon-rf'

Parameters

Both parameters are required query strings, each drawn from the fixed mount-id enum in the next section. Calling the endpoint with neither parameter returns a 400 with the full list of ids in the body — handy for one-shot discovery.

Request parameters
FieldTypeDescription
lensstring (mount id, required)The lens-side mount — what you have. Example: canon-ef, nikon-f, m42, leica-m.
bodystring (mount id, required)The body-side mount — what you want to mount onto. Example: canon-rf, sony-e, micro-four-thirds, fujifilm-x.

Mount ids

27 accepted ids — same slugs used in /mount/<id> URLs. Any other value returns 404. Each id below links to the human-readable page for that mount.

Response schema

Successful responses are an object with three top-level keys: lens, body, and compat. Real example — Canon EF lens on a Canon RF body:

{
  "lens": {
    "id": "canon-ef",
    "displayName": "Canon EF",
    "manufacturer": "Canon",
    "flangeDistanceMm": 44,
    "electronicProtocol": "Canon EF"
  },
  "body": {
    "id": "canon-rf",
    "displayName": "Canon RF",
    "manufacturer": "Canon",
    "flangeDistanceMm": 20,
    "electronicProtocol": "Canon RF"
  },
  "compat": {
    "lensMountId": "canon-ef",
    "bodyMountId": "canon-rf",
    "feasibility": "mechanical",
    "af": "full",
    "is": "full",
    "aperture": "electronic",
    "infinityFocus": "yes",
    "adapterExamples": [
      "Canon EF-EOS R (plain)",
      "Canon EF-EOS R with Control Ring",
      "Canon EF-EOS R Drop-In Filter (Variable ND / Circular Polarizer)"
    ],
    "caveats": [
      "Every Canon EF lens since 1987 preserves full AF, IS, and electronic aperture.",
      "EF-S lenses auto-crop to APS-C; full-frame RF bodies switch to 1.6× crop mode."
    ],
    "formatNote": {
      "match": "match",
      "lensFormat": "full-frame",
      "bodyFormat": "full-frame",
      "cropFactor": null,
      "message": "Lens image circle (full-frame) matches body sensor (full-frame) — no crop or vignetting concern."
    }
  }
}

lens and body objects

Both carry the same shape — mount metadata echoed from the requested ids:

lens / body object fields
FieldTypeDescription
idstringStable mount slug — same id used in /mount/<id> URLs.
displayNamestringHuman-readable name (e.g. "Canon EF", "Sony E (incl. FE)").
manufacturerstringOwning manufacturer / standards body.
flangeDistanceMmnumberFlange focal distance in millimetres.
electronicProtocolstringElectronic mount protocol family, or "mechanical-only" for passive mounts.

compat object

The compatibility verdict and its components:

compat object fields
FieldTypeDescription
lensMountIdstringEchoes the requested lens mount id (e.g. canon-ef).
bodyMountIdstringEchoes the requested body mount id (e.g. canon-rf).
feasibility"native" | "mechanical" | "requires-glass" | "impossible"Can this lens-on-body combination work at all? native = same mount; mechanical = plain adapter spans the flange gap; requires-glass = focal reducer or correction optics needed (lens cannot otherwise reach infinity); impossible = body flange exceeds lens flange and no commercial solution exists.
af"full" | "partial" | "focus-confirm" | "manual-only" | "n/a"Autofocus preserved through the adapter. full = both AF-S and AF-C; partial = AF-S only or slower; focus-confirm = green-dot beep only; manual-only = lens has no AF motor on this combination.
is"full" | "lens-only" | "none" | "n/a"Image-stabilisation pass-through. full = both lens OIS + body IBIS coordinate; lens-only = OIS works but IBIS does not coordinate (or vice-versa); none = stabilisation does not engage.
aperture"electronic" | "manual-ring" | "adapter-wheel" | "stuck-open" | "n/a"How the aperture is controlled. electronic = body commands the lens diaphragm over the smart adapter; manual-ring = lens has a physical aperture ring; adapter-wheel = the adapter itself has a control ring; stuck-open = no way to stop down on this combination.
infinityFocus"yes" | "requires-correction" | "no"Whether the lens can focus at infinity through the adapter. requires-correction signals a focal-reducer or corrective-optic adapter is needed; no means the geometry leaves the lens always focused closer than infinity.
adapterExamplesstring[]Representative real-world SKUs we have verified for this combination. Not exhaustive; ordering is not a ranking.
caveatsstring[]Plain-English notes — known firmware quirks, lens-family limits, AF-speed penalties, EF-S/DX auto-crop behaviour, and so on.
formatNoteFormatNote | nullSensor / image-circle relationship between lens and body. null when both sides cover the same format.

compat.formatNote object

Present whenever lens and body cover different sensor formats — null otherwise.

compat.formatNote object fields
FieldTypeDescription
match"match" | "lens-larger-than-body" | "lens-smaller-than-body"Direction of any image-circle mismatch. match = no mismatch.
lensFormatstringLargest format the lens covers (e.g. "full-frame", "APS-C", "MFT").
bodyFormatstringLargest format the body sensor uses.
cropFactornumber | nullEffective focal-length multiplier when a larger-image-circle lens is mounted on a smaller-sensor body. null when match = match.
messagestringHuman-readable summary of the mismatch — surfaced verbatim as the amber callout on every relevant /matrix cell and /sku/[slug] page.

Responses carry Cache-Control: public, max-age=3600, s-maxage=86400 — safe to cache aggressively. Mount-data revisions in this repo update the response within one hour for clients and one day for any shared cache.

Errors

Two error shapes. Both include the full knownMountIds array so clients can self-correct without a separate discovery call.

400 missing_params

Returned when either lens or body is absent from the query string.

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "missing_params",
  "message": "Both ?lens=<mount-id> and ?body=<mount-id> are required. See /api/compat (no args) for the list of mount ids.",
  "knownMountIds": ["canon-ef", "canon-ef-s", "canon-rf", "…"]
}

404 unknown_mount

Returned when one or both ids are not in the accepted enum. The response tells you which side failed — useful for forms that bind two dropdowns.

HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "error": "unknown_mount",
  "message": "One or both mount ids are not recognised.",
  "provided": { "lens": "ef-mark-iv", "body": "canon-rf" },
  "lensFound": false,
  "bodyFound": true,
  "knownMountIds": ["canon-ef", "canon-ef-s", "canon-rf", "…"]
}

What this powers

The same dataset backs the rest of the site — the cross-brand matrix (every cell), the adapter picker (lens + body lookups), the per-mount deep pages, and the adapter SKU index. If a cell on the matrix is correct, the API call for the same two ids will return the same verdict. If it is wrong on one, it is wrong on both — please report.

Limits & terms

  • No rate limit at low volume. The endpoint is static-data + a small computation, served behind Cloudflare; a well-behaved client doing hundreds of requests a day will not be throttled. Sustained automation above that — kiosk fleets, rental-shop point-of-sale, batch enrichment of large lens inventories — should consider the pro tier below.
  • Attribution requested. If you publish results derived from this API (a blog post, a comparison table, a YouTube video card), please credit lensmount.hk2.ai with a link. Not legally required, but it is how this stays free.
  • Informational only.Adapter compatibility data is drawn from manufacturer documentation, published teardowns, and reproducible AF tests. Verify against the manufacturer's current compatibility chart before any purchase decision — firmware updates and SKU revisions occasionally change behaviour after this site is updated.
  • No personal data. The endpoint takes two parameters, neither tied to a user. We do not log per-request IP addresses beyond what Cloudflare retains for abuse mitigation — see the privacy policy.

Roadmap

Planned higher-tier access — keyed, higher rate limits, batch lookups, per-SKU detail (firmware history, electronic-contact count) — for camera-store kiosks and rental-shop point-of-sale systems via the same pro tier that powers saved kit recommendations. Not live yet; this page is the place we will publish the key request flow when it is.

Common questions

Is there a rate limit on the /api/compat endpoint?
No hard rate limit at low volume. The endpoint serves static data plus a small computation behind Cloudflare, so well-behaved clients doing several hundred requests per day will not be throttled. The response carries Cache-Control: public, max-age=3600, s-maxage=86400, so a correctly-configured client only re-fetches the same mount pair once an hour anyway. Sustained automation above that — kiosk fleets, rental-shop point-of-sale, batch enrichment of large lens inventories — should plan to use the keyed pro tier outlined in the Roadmap section above when it ships.
How often does the underlying compatibility data change, and how aggressively can I cache responses?
Mount specs and adapter-SKU data live as static JSON in this repo and only update when manufacturer firmware revisions, new adapter releases, or fresh AF-test results justify a change — typical cadence is weeks, not minutes. Each response carries Cache-Control: public, max-age=3600, s-maxage=86400, so client caches see new data within one hour and any shared CDN cache within one day. If you mirror responses into your own datastore, refreshing weekly is more than sufficient for any consumer-facing use; nightly is plenty even for retail-floor kiosks.
Does the API include per-lens-model data, or only per-mount?
Both, partially. The ?lens= parameter accepts either a mount id (canon-ef, nikon-f, sony-e — the entire mount-to-mount class) or a lens slug (ef-70-200-f2.8l-is-iii, fe-70-200-f2.8-gm-ii, z-70-200-f2.8-vr-s — a specific lens model). When you pass a lens slug, the response includes a top-level lensModel object alongside the existing lens / body / compat blocks, with manufacturer, focal length range, max aperture, weight, release year, image stabilisation, and prime-vs-zoom classification. The first batch covers roughly 30 popular EF / FE / Z / RF lenses; the long tail (vintage M42, K-mount Limited primes, OM Zuiko, GFX, X-mount) will be added in subsequent updates. Mount-id queries continue to work unchanged. Lens-model-specific verdicts (known-good / known-issue behaviour per lens through a specific adapter SKU) remain on the /sku/[slug] adapter pages, since that data is SKU × lens, not mount × lens.
Will the JSON response schema change without warning?
Top-level field names — lens, body, compat, and the keys inside compat (feasibility, af, is, aperture, infinityFocus, adapterExamples, caveats, formatNote) — are considered stable. They map 1:1 to user-facing surfaces across the rest of the site, so renaming them would break the site itself. Additive changes (new optional fields, new entries inside enum unions like aperture: "adapter-wheel" or feasibility: "requires-glass") may ship without notice — build clients that ignore unknown fields rather than rejecting them. If a breaking schema change ever became necessary, it would land at a new path (/api/v2/compat); the v1 path will not be redefined in place.
Can I use the API commercially, and is attribution required?
Yes, commercial use is fine, and attribution is requested but not legally required. If you publish derived results in a blog post, a comparison table, a YouTube video card, a kiosk UI, an embedded buyer's-guide widget, or anywhere similar, a link back to lensmount.hk2.ai is what keeps this site free. The data is informational only and drawn from public manufacturer documentation, published teardowns, and reproducible AF tests — always verify against the manufacturer's current compatibility chart before any purchase decision your users will rely on. See the Limits & terms section above for the full conditions.