This is the full developer documentation for DoesItARM # DoesItARM > Know instantly whether any Mac app or game runs on Apple Silicon — native, through Rosetta 2, through a translation layer, or not at all — and keep that answer current as the world changes. The consumer site is live [doesitarm.com](https://doesitarm.com) answers “does it run on Apple Silicon?” for thousands of Mac apps and games today — with the chip, the macOS version, the date, and the evidence behind every verdict. The API is a Preview spec The developer **API & MCP server** under [/api](/api/) are documented here as a spec — written as if they work, so they can be reviewed before they ship. Every API page is badged **Preview**. ## Start here [Section titled “Start here”](#start-here) [How verdicts work ](/overview/how-verdicts-work/)The mental model: status, confidence, basis, freshness — and the Rosetta 2 deadline. [API Quickstart ](/api/quickstart/)Your first verdict in 60 seconds — one request, no key. [The Verdict object ](/api/verdict/)The one shape everything returns, every field annotated. [MCP server ](/api/mcp/)The same four read-only tools an AI agent can call directly. Why “as if it works”? DoesItARM’s whole pitch is being a **trustworthy, current** source of truth. The docs are written in present tense so the design is concrete and reviewable — but the consumer site is **live** while the API is a **Preview** spec. Those two truths never blur: product pages carry no badge; every API page is badged Preview. # API overview > A read-only API and MCP server that returns a current Apple Silicon verdict in one request. Free to read, paid for capability. Preview — documented before it ships This is the API’s spec, written as if it works. Endpoints return the shapes documented here. If you’re an early integrator and a response differs from a page, that’s drift — [tell us](/api/access/free-signup/). The **consumer site is live**; the **API is Preview**. The surface for software. AI assistants, IDE plugins, and IT tools ask DoesItARM for a **current, machine-readable verdict** — native, Rosetta 2, a translation layer, or unsupported — instead of scraping a web page. No commercial API sells “is X native on Apple Silicon” today. This is the gap DoesItARM fills. ## Read-only by design [Section titled “Read-only by design”](#read-only-by-design) Every operation is a **query**. Nothing writes, buys, emails, or changes state. That’s deliberate: a read-only tool can’t be hijacked into a harmful action, which dodges the MCP prompt-injection risk and makes the tool safe to drop into an autonomous agent’s toolset. Trust is the product. ## Free data, paid capability [Section titled “Free data, paid capability”](#free-data-paid-capability) The verdict facts are **free** and published under [CC BY 4.0](/api/citation/) — look one up, cite it, build on it. You pay only for **capability** that the free single lookup can’t give you: bulk access, the change feed, a freshness guarantee, a redistribution license, or enterprise reports. We never meter the volume of the single lookup itself. | Capability | Tool | Tier | | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ---- | | Look up one current verdict | `lookup_verdict` · [`GET /verdicts/{identifier}`](/api/reference/operations/lookupverdict/) | Free | | Search / disambiguate a title | `search_titles` · [`GET /titles`](/api/reference/operations/searchtitles/) | Free | | Browse a category | `list_by_category` · [`GET /categories/{category}/verdicts`](/api/reference/operations/listbycategory/) | Free | | The change feed (monitoring) | `whats_changed_since` · [`GET /changes`](/api/reference/operations/whatschangedsince/) | Paid | | Bulk / export · SLA · license · enterprise reports | — | Paid | See [Pricing](/api/pricing/) for the plans and the machine-readable block agents read. ## Pick your path [Section titled “Pick your path”](#pick-your-path) [Quickstart ](/api/quickstart/)One unauthenticated request returns a real verdict — no key, 60 seconds. [The Verdict object ](/api/verdict/)The one shape every endpoint returns, with the honesty fields explained. [MCP server ](/api/mcp/)The same four tools, callable directly by an AI agent. [API Reference ](/api/reference/)Generated from the OpenAPI spec — every operation and schema. ## Get access [Section titled “Get access”](#get-access) Three doors. Each row states its cost — the word “free” never sits next to a door that takes a card. | Door | Who it’s for | Cost | | ----------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------- | | [Free signup](/api/access/free-signup/) | Devs who want a key with higher limits than anonymous | **Free** — no card | | [Early Access](/api/access/early-access/) | Devs who want the paid capability axes now | **Paid pre-sale** — card pre-authorized, charged only on delivery | | [Apply — Enterprise](/api/access/apply/) | IT teams scanning a fleet against the Rosetta 2 deadline | **Free to qualify** → priced pilot | You don’t need any of them to start: the [Quickstart](/api/quickstart/) works anonymously. Cross-link, never guess — the narrative “why” lives in [How verdicts work](/overview/how-verdicts-work/); this section is the callable contract. # Apply — Enterprise > The fleet door — free to qualify, routes to a priced pilot. No card on this page. Preview — documented before it ships The enterprise readiness product is in Preview. Applying starts a conversation; it is not a purchase. The door for **IT teams and MSPs** facing the **Rosetta 2 removal in macOS 28 (fall 2027)** across a fleet of Intel-only apps. This is **free to qualify** and routes to a **priced pilot** — there’s no card on this page. ## What the pilot delivers [Section titled “What the pilot delivers”](#what-the-pilot-delivers) * A **readiness scan** of your software estate against the Rosetta 2 deadline — which apps are native, which only survive via Rosetta (`breaksAtRosettaEol`), which are unsupported. * A **remediation plan**: native replacements and [alternatives](/api/citation/) for what won’t survive. * **Monitoring** as verdicts change, powered by the [change feed](/api/reference/operations/whatschangedsince/). Only app/plugin **identifiers and architecture** are sent for a scan — never your binaries or user data. ## How qualifying works [Section titled “How qualifying works”](#how-qualifying-works) Tell us your company, rough fleet size, and use case. That routes you to a scoped, priced pilot conversation — not an instant checkout. (Buyer ≠ user: the admin who feels the deadline can start this without holding the budget; see [Who it’s for](/overview/who-its-for/).) If you’re an individual developer rather than a fleet, you probably want [Early Access](/api/access/early-access/) instead. [Apply for an enterprise pilot →](https://doesitarm.com/enterprise/apply) *Applying routes to `https://doesitarm.com/enterprise/apply`.* # Early Access > The paid self-serve door — an early-access pre-sale. Card pre-authorized, charged only on delivery. Preview — documented before it ships The paid API isn’t live. Early Access is a genuine **pre-sale**, not an active subscription — read exactly how it works below. The developer door to the **paid capability axes**. Early Access is an **early-access pre-sale**: you reserve access at founding pricing now, and you’re charged only when access is actually delivered. ## How the pre-sale works [Section titled “How the pre-sale works”](#how-the-pre-sale-works) * You place a **card pre-authorization** through Stripe. * You are **charged only on delivery** — when your paid key is live. No delivery, no charge. * **Access is not instant.** This reserves your spot and your price; it does not flip a paid key on today. This is deliberately not a “buy now” button for something that doesn’t exist yet. The door is real — just early. If you only want to be *notified*, use [Free signup](/api/access/free-signup/) instead; if you’re an IT team scanning a fleet, use [Apply](/api/access/apply/). ## What it unlocks (on delivery) [Section titled “What it unlocks (on delivery)”](#what-it-unlocks-on-delivery) A `dia_live_` key with the paid axes from [Pricing](/api/pricing/): * the [change feed](/api/reference/operations/whatschangedsince/) (`whats_changed_since`), * bulk / export, * a freshness SLA, * a commercial-redistribution [license](/api/citation/). Until then, the free reads work [anonymously](/api/authentication/) or with a [free key](/api/access/free-signup/). [Reserve Early Access →](https://doesitarm.com/early-access) *Reserving routes to `https://doesitarm.com/early-access`, where the card pre-authorization is placed.* # Free signup > A free API key with higher limits than anonymous — no card. Not Early Access. Preview — documented before it ships Signup isn’t open yet. This page describes what a free key grants and links where to be notified. The no-card door. Create a **free API key** to read DoesItARM with **higher rate limits than anonymous**, and get the changelog email so you know when the API goes live. ## What you get [Section titled “What you get”](#what-you-get) * A `dia_free_` key (see [Authentication](/api/authentication/)). * **Higher rate limits** than anonymous calls — a known caller gets a bigger budget than an IP bucket. * The full free reads: [lookup](/api/reference/operations/lookupverdict/), [search](/api/reference/operations/searchtitles/), and [category browse](/api/reference/operations/listbycategory/). * The API changelog by email. ## What you don’t get [Section titled “What you don’t get”](#what-you-dont-get) This is **not** [Early Access](/api/access/early-access/). A free key does **not** unlock the paid capability axes — the [change feed](/api/reference/operations/whatschangedsince/), bulk/export, the freshness SLA, the redistribution license, or enterprise reports. For those, see [Early Access](/api/access/early-access/) (developers) or [Apply](/api/access/apply/) (fleets). ## You may not even need a key [Section titled “You may not even need a key”](#you-may-not-even-need-a-key) The [Quickstart](/api/quickstart/) works with **no credential at all** — anonymous calls are rate-limited per IP. Sign up when you want a larger budget or want to be told when the API ships. [Create a free key →](https://doesitarm.com/api-signup) # Authentication & API keys > Three tiers — anonymous, free key, and paid — all on the standard Bearer header. Preview — documented before it ships This describes the auth model the API will use. No keys are issued yet — get notified at [Free signup](/api/access/free-signup/). DoesItARM reads are designed to be reachable with **no credential at all**. You add a key only to raise your limits or to unlock a paid capability. ## Three tiers [Section titled “Three tiers”](#three-tiers) | Tier | How you call | What you get | | ------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Anonymous** | No header | The free reads ([lookup](/api/reference/operations/lookupverdict/), [search](/api/reference/operations/searchtitles/), [category](/api/reference/operations/listbycategory/)), rate-limited per IP — the lowest bucket. | | **Free key** | `Authorization: Bearer dia_free_…` | The same free reads, with **higher limits** than anonymous, plus the changelog email. No card. [Get one →](/api/access/free-signup/) | | **Paid** | `Authorization: Bearer dia_live_…` | Everything above **plus the paid capability axes** — the [change feed](/api/reference/operations/whatschangedsince/), bulk/export, a freshness SLA, a redistribution license. [Early Access →](/api/access/early-access/) | ## The header [Section titled “The header”](#the-header) Send your key as a standard HTTP **Bearer** token — the same scheme Stripe and OpenAI use, so most agent frameworks handle it for free: ```bash curl https://api.doesitarm.com/v1/changes?since=2026-06-01 \ -H "Authorization: Bearer dia_live_xxxxxxxxxxxxxxxxxxxx" ``` ## Key prefixes [Section titled “Key prefixes”](#key-prefixes) Every key carries a prefix so it’s unmistakable — and greppable if it leaks: * `dia_free_` — issued by [free signup](/api/access/free-signup/); no card, higher-than-anonymous limits. * `dia_test_` — sandbox; safe in examples and CI. * `dia_live_` — paid; unlocks the paid capabilities. ## When you need a key [Section titled “When you need a key”](#when-you-need-a-key) * **You don’t,** to look up, search, or browse — those are free, anonymously. Start at the [Quickstart](/api/quickstart/). * **For higher free limits,** create a [free key](/api/access/free-signup/). * **For the [change feed](/api/reference/operations/whatschangedsince/) or any paid axis,** you need a `dia_live_` key — see [Early Access](/api/access/early-access/). Calling a paid route without a valid key returns `401`; calling it with a key that lacks the capability returns `403`. Both use the standard [error envelope](/api/errors/). # Caching & freshness > How to cache verdicts safely, and how the API tells you when an answer has decayed. Preview — documented before it ships This is the intended caching contract. A verdict is a **cacheable fact** — and a *decaying* one. The API gives you both: validators so you can cache cheaply, and explicit signals so you know when an answer has gone stale. ## Validators [Section titled “Validators”](#validators) A verdict response carries: | Header | Meaning | | --------------- | ----------------------------------------------------------------- | | `ETag` | Stable hash over `(slug, macosVersion, chip, lastVerified)` | | `Last-Modified` | Mirrors the verdict’s `lastVerified` date | | `Cache-Control` | `public, max-age=3600, stale-while-revalidate=86400` for verdicts | Revalidate cheaply with a conditional request — an unchanged verdict returns `304` with no body: ```bash curl https://api.doesitarm.com/v1/verdicts/slug:adobe-photoshop \ -H 'If-None-Match: "abc123"' # → 304 Not Modified if the verdict hasn't changed ``` ## No `Vary: Authorization` on verdicts [Section titled “No Vary: Authorization on verdicts”](#no-vary-authorization-on-verdicts) A verdict body is **tier-independent** — a free caller and a paid caller get the *identical* verdict for the same `(slug, macosVersion, chip)`. So verdict responses are `public` and are **not** varied on `Authorization`; splitting the cache per key would fragment the CDN for zero benefit (and `public` + `Vary: Authorization` is a known shared-cache footgun). Genuinely key-scoped responses — the paid [change feed](/api/reference/operations/whatschangedsince/) — are marked `Cache-Control: private` instead. ## Freshness signals [Section titled “Freshness signals”](#freshness-signals) Freshness is the product’s promise, so it’s explicit in the response, not implied by age: * **`stale`** (body field) — `true` when the verdict is past its freshness threshold and a re-test is queued. You still get the last known answer. * **`X-DoesItARM-Stale`** (header) — the same signal, readable without parsing the body. * **`lastVerified`** (body) / **`Last-Modified`** (header) — when the answer was last confirmed. Treat `stale: true` as “trust, but re-check soon” — not as an error. Re-tests fire on a new macOS or Game Porting Toolkit release, an app update, a report surge, or a scheduled cadence; the [change feed](/api/reference/operations/whatschangedsince/) tells you the moment a cached verdict actually changed, so you can invalidate precisely instead of polling. The concept behind all of this is [How verdicts work](/overview/how-verdicts-work/). # Changelog > Contract changes to the API and the spec, newest first — distinct from the data change feed and the product changelog. Preview — documented before it ships The API isn’t live, so this changelog tracks the *spec* for now. Once the API ships, every contract change lands here, labeled breaking or non-breaking. This is the **contract** changelog — changes to endpoints, schemas, and the OpenAPI document. Two things it is **not**: * the **[data change feed](/api/reference/operations/whatschangedsince/)** — that’s verdicts *moving* (Photoshop went native), a paid API feed, not a human page; and * the **product changelog** on [doesitarm.com](https://doesitarm.com) — that’s the consumer site’s release notes. See [Versioning](/api/versioning/) for what “breaking” means and why `info.version` and the `/v1` URL are two different numbers. ## Entries [Section titled “Entries”](#entries) ### `1.0.0` — Preview spec published non-breaking [Section titled “1.0.0 — Preview spec published non-breaking”](#100--preview-spec-published-non-breaking) *2026-06-27* * First public draft of the DoesItARM API spec, written as a reviewable Preview. * Four read-only operations: `lookupVerdict`, `searchTitles`, `listByCategory`, `whatsChangedSince` — mirrored as MCP tools. * The [Verdict object](/api/verdict/) and its related schemas (`Signal`, `Alternative`, `SearchResult`, `ChangeRecord`, `Pagination`, `Error`) finalized against the live data model. * The single [error envelope](/api/errors/), [rate-limit headers](/api/rate-limits/), and [cursor pagination](/api/pagination/) defined. * `Authorization: Bearer dia_*` [auth](/api/authentication/) with free / test / live key prefixes. *Nothing here is live yet — there are no breaking changes to report because there is no prior published contract.* # Agents & citation > Give-vs-gate, the CC BY license, the citable unit, and the JSON-LD payload for AI answers. Preview — documented before it ships The citation surfaces described here are part of the API spec. DoesItARM *wants* to be cited. The whole strategy is **give-vs-gate**: give away the verdict facts so DoesItARM becomes the default answer everywhere agents look, and gate only the capability that can’t be reconstructed from a single lookup. ## What’s free to reuse [Section titled “What’s free to reuse”](#whats-free-to-reuse) Verdict facts are published under **[Creative Commons Attribution 4.0 (CC BY)](https://creativecommons.org/licenses/by/4.0/)**. You may reuse them — in an app, a comparison table, or an AI assistant’s answer — with attribution to DoesItARM. That covers the answer, the named alternative, and the last-checked date: the things a user actually needs. What’s **gated** is [capability](/api/pricing/), not facts: bulk export, the change feed, a freshness SLA, a redistribution license, and enterprise reports. Those can’t be rebuilt from one free lookup, so they’re where the paid line sits. ## The citable unit [Section titled “The citable unit”](#the-citable-unit) When an agent answers “can I run X on my Mac?”, cite three things so the user can verify and re-check: 1. the **verdict** (`status`, and the layer if `translation`), 2. the **named alternative** if it’s unsupported, and 3. the **`lastVerified` date** — because a compatibility answer decays. > Adobe Photoshop runs **natively** on Apple Silicon (DoesItARM, last verified 2026-06-21). ## Machine-readable payloads [Section titled “Machine-readable payloads”](#machine-readable-payloads) Every verdict page on doesitarm.com embeds **JSON-LD** so crawlers and agents can lift a structured, attributable claim without scraping prose: ```json { "@context": "https://schema.org", "@type": "SoftwareApplication", "name": "Adobe Photoshop", "operatingSystem": "macOS 26 (Apple Silicon)", "url": "https://doesitarm.com/adobe-photoshop", "additionalProperty": [ { "@type": "PropertyValue", "name": "appleSiliconStatus", "value": "native" }, { "@type": "PropertyValue", "name": "lastVerified", "value": "2026-06-21" } ], "license": "https://creativecommons.org/licenses/by/4.0/" } ``` A Markdown mirror of each verdict is available for agents that prefer text, and the whole site is summarized for LLMs at [`/llms.txt`](/llms.txt) and [`/llms-full.txt`](/llms-full.txt). The OpenAPI contract itself is published at [`/openapi.yaml`](/openapi.yaml), and machine-readable pricing at [`/api/pricing.json`](/api/pricing.json) — so an agent framework can discover the tool, its cost, and its license without a human in the loop. Why give the facts away An agent that can cite DoesItARM for free, with a date, will keep coming back as the answer decays — which is exactly the position the paid capabilities are sold from. Free facts buy the ubiquity; capability is the till. See [Pricing](/api/pricing/). # Errors > One envelope, one parse path. Branch on code; read message; no 3xx ever carries an error. Preview — documented before it ships This is the error contract the API will honor. There is **one error envelope** for every 4xx and 5xx. Agents branch on `code`; humans read `message`; you write one parse path. No `3xx` ever carries an error body. ## The envelope [Section titled “The envelope”](#the-envelope) ```json { "error": { "type": "invalid_request", "code": "ambiguous", "message": "12 titles match \"office\". Pass a slug: or steam: identifier.", "docsUrl": "https://docs.doesitarm.com/api/errors/#ambiguous", "suggestions": [{ "slug": "microsoft-office", "title": "Microsoft Office", "score": 0.82 }], "requestId": "req_01J5K6Q8Z9" } } ``` * **`type`** — coarse family: `invalid_request`, `rate_limited`, `auth`, `server`. (`ambiguous` is a `code`, sent under `type: invalid_request`.) * **`code`** — the precise branch (closed set below). Branch on this. * **`message`** — human-readable; names the offending field where relevant. * **`docsUrl`** / **`upgradeUrl`** — where to read more, or how to unblock. * **`suggestions`** — present on `ambiguous`: candidates to re-query with. * **`requestId`** — quote it to support. ## The full table [Section titled “The full table”](#the-full-table) | Case | HTTP | `type` | `code` | What to do | | ----------------- | ------- | ----------------- | --------------- | ------------------------------------------------------------------------------ | | Unknown title | **200** | — | — | Not an error. You get a Verdict with `status: "unknown"`; read `alternatives`. | | Ambiguous lookup | **409** | `invalid_request` | `ambiguous` | Pick from `suggestions[]`; re-query with a `slug:`/`steam:` id. | | Invalid parameter | **422** | `invalid_request` | `invalid_param` | Fix the field `message` names (e.g. a bad `chip`). | | Auth required | **401** | `auth` | `auth_required` | Add an API key (paid-only route). | | Auth invalid | **401** | `auth` | `auth_invalid` | Rotate the key — bad, revoked, or expired. | | Forbidden (tier) | **403** | `auth` | `plan_required` | Upgrade; `docsUrl` → pricing. | | Rate limited | **429** | `rate_limited` | `rate_limited` | Wait `Retry-After`, or upgrade via `upgradeUrl`. | | Server error | **5xx** | `server` | `internal` | Retry with backoff; quote `requestId`. | `unknown` and `stale` are not errors A title with no data returns **200** with `status: "unknown"`. A title past its freshness window returns **200** with `stale: true`. Read them as verdicts — see [The Verdict object](/api/verdict/) and [Caching & freshness](/api/caching/). ## Worked example — ambiguous lookup (409) {#ambiguous} [Section titled “Worked example — ambiguous lookup (409) {#ambiguous}”](#worked-example--ambiguous-lookup-409-ambiguous) A bare name with several strong matches doesn’t guess — it asks you to disambiguate: ```bash curl https://api.doesitarm.com/v1/verdicts/office ``` ```http HTTP/1.1 409 Conflict Content-Type: application/json ``` ```json { "error": { "type": "invalid_request", "code": "ambiguous", "message": "12 titles match \"office\". Pass a slug: or steam: identifier.", "docsUrl": "https://docs.doesitarm.com/api/errors/#ambiguous", "suggestions": [{ "slug": "microsoft-office", "title": "Microsoft Office", "score": 0.82 }], "requestId": "req_01J5K6Q8Z9" } } ``` Re-query with one of the suggestions: `GET /v1/verdicts/slug:microsoft-office`. The other worked example — a `429` and the upgrade path — lives on [Rate limits](/api/rate-limits/). # MCP server > The same four read-only tools an AI agent can call directly — returning the same shapes as REST. Preview — documented before it ships The MCP server is specified here; it isn’t live yet. The tool I/O mirrors the [REST reference](/api/reference/) exactly. The DoesItARM **MCP server** exposes the same capabilities as the REST API as [Model Context Protocol](https://modelcontextprotocol.io) tools, so an AI assistant can ask “does X run on Apple Silicon?” by *calling a tool*, not scraping a page. ## Read-only by design [Section titled “Read-only by design”](#read-only-by-design) All four tools are **queries**. Nothing writes, buys, emails, or mutates state — so the server is safe to add to an autonomous agent without exposing it to a harmful action. That read-only shape is deliberate: it sidesteps the MCP prompt-injection risk class and makes the tools easy to trust and include. ## Connect [Section titled “Connect”](#connect) * Claude Code ```bash claude mcp add doesitarm --transport http https://mcp.doesitarm.com ``` * Claude Desktop / Cursor mcp.json ```jsonc { "mcpServers": { "doesitarm": { "type": "http", "url": "https://mcp.doesitarm.com" // Authorization only needed for the paid whats_changed_since tool: // "headers": { "Authorization": "Bearer dia_live_…" } } } } ``` * VS Code .vscode/mcp.json ```jsonc { "servers": { "doesitarm": { "type": "http", "url": "https://mcp.doesitarm.com" } } } ``` * OpenAI Agents SDK ```python from agents.mcp import MCPServerStreamableHttp doesitarm = MCPServerStreamableHttp( params={"url": "https://mcp.doesitarm.com"} ) ``` The three read tools work with no credential. The paid `whats_changed_since` tool needs an `Authorization: Bearer dia_live_…` header — see [Authentication](/api/authentication/). ## The tools [Section titled “The tools”](#the-tools) Each tool returns **the same payload its REST mirror returns on `200`** — there is no separate wrapper shape. Learn [the Verdict object](/api/verdict/) once and you know all four. | Tool | Returns | REST mirror | Tier | | --------------------- | -------------------------------------- | ---------------------------------------------------------------------------------- | -------- | | `lookup_verdict` | one [`Verdict`](/api/verdict/) | [`GET /verdicts/{identifier}`](/api/reference/operations/lookupverdict/) | Free | | `search_titles` | `{ data: SearchResult[], pagination }` | [`GET /titles`](/api/reference/operations/searchtitles/) | Free | | `list_by_category` | `{ data: Verdict[], pagination }` | [`GET /categories/{category}/verdicts`](/api/reference/operations/listbycategory/) | Free | | `whats_changed_since` | `{ data: ChangeRecord[], pagination }` | [`GET /changes`](/api/reference/operations/whatschangedsince/) | **Paid** | ## Example call [Section titled “Example call”](#example-call) * MCP tool ```text Tool: lookup_verdict Arguments: { "identifier": "slug:adobe-photoshop" } → Verdict { status: "native", confidence: "high", stale: false, … } ``` * REST equivalent ```bash curl https://api.doesitarm.com/v1/verdicts/slug:adobe-photoshop ``` Errors are tool errors Rate limits and other failures surface as MCP **tool errors** (the protocol’s `isError` result) carrying the same [error envelope](/api/errors/) — an over-limit call is a tool error with `code: rate_limited` and a `Retry-After`, mirroring REST `429`, not a success payload that secretly means “no”. `unknown` and `stale` are **not** errors — they come back as a normal `Verdict`. ## Why agents should reach for it [Section titled “Why agents should reach for it”](#why-agents-should-reach-for-it) [Always current ](/api/caching/)Training data goes stale; this returns lastVerified and stale so you know when to trust it. [Citable ](/api/citation/)Verdict facts are CC BY — cite the answer, the alternative, and the date. # Pagination > Cursor-based traversal for the list and search endpoints, with one envelope and one loop. Preview — documented before it ships This is the pagination contract for the list-returning endpoints. The list-returning endpoints — [search](/api/reference/operations/searchtitles/), [category](/api/reference/operations/listbycategory/), and the paid [change feed](/api/reference/operations/whatschangedsince/) — page with an **opaque cursor**. The single-title [lookup](/api/reference/operations/lookupverdict/) returns one object and never paginates. ## The envelope [Section titled “The envelope”](#the-envelope) Every paged response wraps its rows in `data` and carries a `pagination` block: ```json { "data": [ /* SearchResult[] or Verdict[] or ChangeRecord[] */ ], "pagination": { "nextCursor": "eyJ2IjoyfQ", "hasMore": true } } ``` * **`nextCursor`** — an **opaque** token. Pass it back as `?cursor=` to get the next page. It is `null` on the last page. Never parse or construct it; its format can change. * **`hasMore`** — `true` when another page exists. ## Page size [Section titled “Page size”](#page-size) Use `limit` (default `50`, max `100`). Larger `limit` means fewer round trips; the cap keeps any single response bounded. ```bash curl "https://api.doesitarm.com/v1/categories/productivity/verdicts?limit=100" ``` ## A full loop [Section titled “A full loop”](#a-full-loop) Walk every page until `nextCursor` is `null`: ```js async function* allVerdicts(category) { let cursor = null do { const url = new URL( `https://api.doesitarm.com/v1/categories/${category}/verdicts` ) url.searchParams.set("limit", "100") if (cursor) url.searchParams.set("cursor", cursor) const { data, pagination } = await (await fetch(url)).json() yield* data cursor = pagination.nextCursor } while (cursor !== null) } for await (const verdict of allVerdicts("productivity")) { console.log(verdict.slug, verdict.status) } ``` Each page still carries the [rate-limit headers](/api/rate-limits/), so honor `RateLimit-Remaining` while looping. For keeping a large local copy current, prefer the [change feed](/api/reference/operations/whatschangedsince/) over re-walking every page. # Pricing > Free data, paid capability — the plans, the capability axes, and the machine-readable block agents read. Preview — documented before it ships Plans and capabilities are fixed below; exact prices are set during [Early Access](/api/access/early-access/), so the machine-readable block carries `"status": "preview"` rather than final numbers. DoesItARM prices on one principle: **free data, paid capability.** The verdict facts are free to read and [cite](/api/citation/). You pay only for *capability* the free single lookup can’t give you — never for the volume of the lookup itself. ## Plans [Section titled “Plans”](#plans) | | Free | Early Access Paid | Enterprise | | ----------------------------------------- | ------------------------------------------- | -------------------------------------------------- | ------------------------------ | | **Lookup, search, browse** | ✅ | ✅ | ✅ | | **Verdict facts (CC BY)** | ✅ | ✅ | ✅ | | **Higher rate limits** | with a [free key](/api/access/free-signup/) | ✅ | ✅ | | **Change feed** (`whats_changed_since`) | — | ✅ | ✅ | | **Bulk / export** | — | ✅ | ✅ | | **Freshness SLA** | — | ✅ | ✅ | | **Commercial-redistribution license** | — | ✅ | ✅ | | **Fleet readiness + remediation reports** | — | — | ✅ | | **How to get it** | [Free signup](/api/access/free-signup/) | [Early Access](/api/access/early-access/) | [Apply](/api/access/apply/) | | **Cost** | $0, no card | Paid pre-sale (card pre-auth, charged on delivery) | Free to qualify → priced pilot | ## The paid axes are orthogonal [Section titled “The paid axes are orthogonal”](#the-paid-axes-are-orthogonal) None of the paid capabilities is “more single lookups.” They’re *different axes* a free caller doesn’t need but a serious one can’t avoid: * **Change feed** — monitor a catalog without re-polling each title. * **Bulk / export** — pull a whole category or the full dataset at once. * **Freshness SLA** — a guaranteed re-test cadence for the titles you depend on. * **Redistribution license** — ship the data inside your own product. * **Enterprise reports** — a fleet audit and remediation plan against the Rosetta 2 deadline. ## Machine-readable [Section titled “Machine-readable”](#machine-readable) Agent frameworks can read the plans and capabilities — with each capability tagged to the tool it gates — at **[`/api/pricing.json`](/api/pricing.json)**, so a tool-using agent can reason about cost before it calls. The OpenAPI contract is at [`/openapi.yaml`](/openapi.yaml) and a discovery catalog at [`/.well-known/api-catalog`](/.well-known/api-catalog). ## Get access [Section titled “Get access”](#get-access) [Free signup ](/api/access/free-signup/)A free key with higher limits than anonymous. No card. [Early Access ](/api/access/early-access/)The paid capabilities — an early-access pre-sale. [Apply — Enterprise ](/api/access/apply/)Scan a fleet against the Rosetta 2 deadline. # Quickstart > Your first verdict in 60 seconds — one request, no key. Preview — documented before it ships The API isn’t live yet. This page shows the exact request and response shape it returns. The fastest path to a real answer: **one unauthenticated request returns one current [Verdict](/api/verdict/).** No key, no signup. 1. **Ask for a verdict** by identifier. Use `slug:`, `steam:`, `bundle:`, or a bare name. * curl ```bash curl https://api.doesitarm.com/v1/verdicts/slug:adobe-photoshop ``` * JavaScript ```js const res = await fetch( "https://api.doesitarm.com/v1/verdicts/slug:adobe-photoshop" ) const verdict = await res.json() console.log(verdict.status) // "native" ``` * Python ```python import requests verdict = requests.get( "https://api.doesitarm.com/v1/verdicts/slug:adobe-photoshop" ).json() print(verdict["status"]) # "native" ``` * MCP ```text Tool: lookup_verdict Arguments: { "identifier": "slug:adobe-photoshop" } → returns the same Verdict object the REST call returns. ``` 2. **Read the answer.** You get one [Verdict](/api/verdict/): ```json { "slug": "adobe-photoshop", "title": "Adobe Photoshop", "kind": "app", "status": "native", "confidence": "high", "basis": ["binary", "vendor", "automated_test"], "macosVersion": "26", "chip": "apple_silicon", "caveats": [], "breaksAtRosettaEol": false, "lastVerified": "2026-06-21", "stale": false, "signals": [ { "id": "sig_01", "kind": "test", "status": "native", "confidence": "high", "macosVersion": "26", "chip": "m3", "at": "2026-06-21T00:00:00Z", "ref": "https://doesitarm.com/adobe-photoshop#test-01" } ], "alternatives": [] } ``` 3. **Scope it** if you care about a specific macOS or chip: ```bash curl "https://api.doesitarm.com/v1/verdicts/slug:cyberpunk-2077?macosVersion=26&chip=m3" ``` ## The branches you should handle [Section titled “The branches you should handle”](#the-branches-you-should-handle) Every example identifier below is real and stable, so you can exercise each branch deterministically: | Identifier | What you get | | ----------------------------- | ------------------------------------------------------------------------- | | `slug:adobe-photoshop` | `native`, high confidence | | `slug:cyberpunk-2077` | `translation`, `translationLayer: "gptk"`, a game | | `slug:figma` | `native` with an Electron caveat in `caveats[]` | | `slug:some-ancient-installer` | `status: "unknown"` plus `alternatives[]` | | `slug:final-cut-pro` | `stale: true` (an intentionally old `lastVerified`) | | `slug:429-demo` | trips the [rate limit](/api/rate-limits/) so you can test your retry path | `unknown` and `stale` are **not errors** — they’re honest verdicts. Read them, don’t throw. Only a genuinely ambiguous name returns an [error](/api/errors/) (`409`). ## What next [Section titled “What next”](#what-next) [The Verdict object ](/api/verdict/)Every field, including the honesty fields, explained. [Authentication ](/api/authentication/)When you need a key, and how the tiers work. [MCP server ](/api/mcp/)Give an AI agent these four tools directly. [API Reference ](/api/reference/operations/lookupverdict/)The full lookupVerdict contract. # Rate limits & tiers > The freemium budget, the headers on every response, and the 429-and-upgrade flow. Preview — documented before it ships The limits below are the intended shape of the freemium budget, not a live SLA. DoesItARM follows **free data, paid capability**: the single-title lookup and search are free; you pay for capability the free read can’t give you. Limits exist to keep the free tier sustainable, not to meter the lookup itself. ## The budget [Section titled “The budget”](#the-budget) | Tier | Reads | Paid capabilities | | -------------------------- | --------------------- | ---------------------------------------------------------- | | **Anonymous** (no key) | Lowest per-IP bucket | — | | **Free key** (`dia_free_`) | Higher per-key bucket | — | | **Paid** (`dia_live_`) | Highest bucket | Change feed, bulk/export, SLA, license, enterprise reports | The exact numbers ship with the live API; treat the tiers, not the integers, as the contract. See [Pricing](/api/pricing/) for plans and the machine-readable block. ## Headers on every response [Section titled “Headers on every response”](#headers-on-every-response) Every response — not just a `429` — carries your remaining budget, so you never have to guess: | Header | Meaning | | --------------------- | -------------------------------------- | | `RateLimit-Limit` | Requests allowed in the current window | | `RateLimit-Remaining` | Requests left in the window | | `RateLimit-Reset` | Seconds until the window resets | These follow the IETF `ratelimit-headers` draft (the pre-08 three-header form, the widest-supported variant). A `429` adds **`Retry-After`** (seconds). ## When you hit the limit [Section titled “When you hit the limit”](#when-you-hit-the-limit) A `429` returns the standard [error envelope](/api/errors/) with both a `Retry-After` header and an `upgradeUrl` in the body: ```http HTTP/1.1 429 Too Many Requests Retry-After: 30 RateLimit-Limit: 60 RateLimit-Remaining: 0 RateLimit-Reset: 30 Content-Type: application/json ``` ```json { "error": { "type": "rate_limited", "code": "rate_limited", "message": "Free tier allows 60 requests/min. Retry in 30s or upgrade.", "docsUrl": "https://docs.doesitarm.com/api/rate-limits/", "upgradeUrl": "https://doesitarm.com/early-access", "requestId": "req_01J5K6Q8ZD" } } ``` **Handle it in two steps:** wait `Retry-After` seconds and retry, or — if you’re hitting the ceiling routinely — follow `upgradeUrl` to [Early Access](/api/access/early-access/). You can trip this deterministically in testing with the `429-demo` identifier from the [Quickstart](/api/quickstart/). # The Verdict object > The one shape every endpoint and tool returns — every field, including the honesty fields, explained. Preview — documented before it ships The shape below is the contract. The [generated reference](/api/reference/operations/lookupverdict/) renders it directly from the OpenAPI spec, nested in each operation’s response. Everything DoesItARM returns is built from one object: the **Verdict**. Learn it once and every endpoint and [MCP tool](/api/mcp/) reads the same. Concept first — the *why* behind these fields is [How verdicts work](/overview/how-verdicts-work/). ## The shape [Section titled “The shape”](#the-shape) ```ts type Verdict = { slug: string // canonical id on doesitarm.com title: string kind: "app" | "game" status: "native" | "rosetta2" | "translation" | "unsupported" | "unknown" translationLayer?: "gptk" | "crossover" | "whisky" | "vm" | null confidence: "high" | "medium" | "low" basis: ("binary" | "automated_test" | "crowd" | "vendor" | "curator")[] macosVersion: string // e.g. "26", "27" chip: string // "apple_silicon" | "m1" | "m2" | "m3" | "m4" caveats: string[] breaksAtRosettaEol: boolean lastVerified: string // ISO date stale: boolean signals: Signal[] // contributing reports/tests, newest first alternatives?: Alternative[] // native equivalents, mainly when unsupported/unknown } ``` ## Field by field [Section titled “Field by field”](#field-by-field) * **`status`** — the answer. `unknown` means *Needs more data*, a real verdict, not a failure. We assert positives/negatives only on strong evidence (a negative needs a *reproduced* failure), so `unknown` is the honest default. * **`translationLayer`** — set only when `status` is `translation`; names the layer (`gptk`, `crossover`, `whisky`, `vm`). `null` or absent otherwise. * **`confidence`** + **`basis`** — how sure we are, and how we know (binary inspection, automated test, crowd reports, vendor statement, curator note). * **`macosVersion`** + **`chip`** — the scope this answer applies to. * **`caveats`** — qualifiers like “no online play” or “low FPS”. * **`breaksAtRosettaEol`** — `true` when the title only survives via Rosetta 2 and will break at macOS 28 (fall 2027). * **`lastVerified`** + **`stale`** — the freshness fields. See [Caching & freshness](/api/caching/). * **`signals`** — the evidence trail, newest first. * **`alternatives`** — native equivalents, surfaced mainly when a title is `unsupported` or `unknown`. The honesty fields are the point `status: "unknown"`, `confidence: "low"`, `stale: true`, and a populated `caveats[]` are features, not edge cases. DoesItARM’s value is being trustworthy — so it tells you what it doesn’t know. Build for these branches first. ## Worked examples [Section titled “Worked examples”](#worked-examples) * native ```json { "slug": "adobe-photoshop", "title": "Adobe Photoshop", "kind": "app", "status": "native", "confidence": "high", "basis": ["binary", "vendor", "automated_test"], "macosVersion": "26", "chip": "apple_silicon", "caveats": [], "breaksAtRosettaEol": false, "lastVerified": "2026-06-21", "stale": false, "signals": [{ "id": "sig_01", "kind": "test", "status": "native", "confidence": "high", "macosVersion": "26", "chip": "m3", "at": "2026-06-21T00:00:00Z", "ref": "https://doesitarm.com/adobe-photoshop#test-01" }], "alternatives": [] } ``` * translation (game) ```json { "slug": "cyberpunk-2077", "title": "Cyberpunk 2077", "kind": "game", "status": "translation", "translationLayer": "gptk", "confidence": "medium", "basis": ["crowd", "automated_test"], "macosVersion": "26", "chip": "apple_silicon", "caveats": ["Runs via Game Porting Toolkit; no anti-cheat online play."], "breaksAtRosettaEol": false, "lastVerified": "2026-06-19", "stale": false, "signals": [{ "id": "sig_8f3", "kind": "report", "status": "translation", "confidence": "medium", "macosVersion": "26", "chip": "m2", "at": "2026-06-19T14:02:00Z", "ref": "https://doesitarm.com/cyberpunk-2077#report-8f3" }], "alternatives": [{ "forSlug": "cyberpunk-2077", "altSlug": "baldurs-gate-3", "reason": "Runs natively on Apple Silicon; similar open-world RPG." }] } ``` * stale ```json { "slug": "final-cut-pro", "title": "Final Cut Pro", "kind": "app", "status": "native", "confidence": "medium", "basis": ["vendor", "crowd"], "macosVersion": "26", "chip": "apple_silicon", "caveats": ["Last verified before macOS 26.2; re-check pending."], "breaksAtRosettaEol": false, "lastVerified": "2025-09-02", "stale": true, "signals": [{ "id": "sig_fcp1", "kind": "source", "status": "native", "confidence": "medium", "macosVersion": "25", "chip": "m2", "at": "2025-09-02T00:00:00Z", "ref": "https://doesitarm.com/final-cut-pro#source-1" }], "alternatives": [] } ``` * unknown ```json { "slug": "some-ancient-installer", "title": "Some Ancient Installer", "kind": "app", "status": "unknown", "confidence": "low", "basis": [], "macosVersion": "26", "chip": "apple_silicon", "caveats": ["No binary or report on file. Submit one to improve this verdict."], "breaksAtRosettaEol": false, "lastVerified": "2026-06-10", "stale": false, "signals": [], "alternatives": [{ "forSlug": "some-ancient-installer", "altSlug": "a-maintained-equivalent", "reason": "Actively maintained, native on Apple Silicon." }] } ``` * rosetta2 ```json { "slug": "quicken-2017", "title": "Quicken 2017", "kind": "app", "status": "rosetta2", "confidence": "high", "basis": ["binary", "crowd"], "macosVersion": "26", "chip": "apple_silicon", "caveats": ["x86_64 only; runs under Rosetta 2 today."], "breaksAtRosettaEol": true, "lastVerified": "2026-06-18", "stale": false, "signals": [{ "id": "sig_qk1", "kind": "report", "status": "rosetta2", "confidence": "high", "macosVersion": "26", "chip": "m2", "at": "2026-06-18T00:00:00Z", "ref": "https://doesitarm.com/quicken-2017#report-qk1" }], "alternatives": [] } ``` `breaksAtRosettaEol: true` — it runs today, but **only** through Rosetta 2, so it stops working at macOS 28 (fall 2027). Plan the migration before then. * unsupported ```json { "slug": "aperture", "title": "Aperture", "kind": "app", "status": "unsupported", "confidence": "high", "basis": ["binary", "crowd"], "macosVersion": "26", "chip": "apple_silicon", "caveats": ["Discontinued by Apple; reproduced failure to launch on macOS 26."], "breaksAtRosettaEol": false, "lastVerified": "2026-06-15", "stale": false, "signals": [{ "id": "sig_ap1", "kind": "test", "status": "unsupported", "confidence": "high", "macosVersion": "26", "chip": "m3", "at": "2026-06-15T00:00:00Z", "ref": "https://doesitarm.com/aperture#test-ap1" }], "alternatives": [{ "forSlug": "aperture", "altSlug": "lightroom-classic", "reason": "Native on Apple Silicon; closest pro photo library and RAW editor." }] } ``` A negative needs a **reproduced** failure (the `caveats` say so), and `alternatives[]` points at a native replacement — the pairing the data model is built around. The related shapes — `Signal` and `Alternative` — are nested inside the `Verdict` and render in full on the [generated `lookupVerdict` reference](/api/reference/operations/lookupverdict/). # Versioning > One URL version, additive within it, breaking changes get a new one — and why there are two version numbers. Preview — documented before it ships This is the versioning policy the API launches with. ## The `/v1` rule [Section titled “The /v1 rule”](#the-v1-rule) The version lives in the **URL path**: `https://api.doesitarm.com/v1/…`. Within a version we make **additive changes only** — new endpoints, new optional fields, new enum *values you can safely ignore*. We never rename or remove a field, change a type, or change the meaning of an existing value inside `v1`. A change that would break a careful client — removing a field, narrowing a type, changing semantics — only ships under a **new path version** (`/v2`), and `/v1` keeps working during a published deprecation window. **Write forward-compatible clients:** ignore fields you don’t recognize, and don’t treat the `status`, `basis`, `confidence`, or `field` enums as exhaustively closed forever — a future additive value should degrade gracefully, not crash your parser. ## Two version numbers, on purpose [Section titled “Two version numbers, on purpose”](#two-version-numbers-on-purpose) You’ll see two numbers and they mean different things: | Number | Where | What it tracks | | ---------------------------- | --------------------------------- | -------------------------------------------------------- | | **`/v1`** | the URL | the **wire contract** — bumped only on a breaking change | | **`info.version` (`1.0.0`)** | the [OpenAPI spec](/openapi.yaml) | the **document** — bumped on every additive revision too | So you can see `info.version` climb to `1.4.0` while the URL stays `/v1`: the spec gained optional fields and endpoints, none of them breaking. When the URL would need to become `/v2`, `info.version` goes to `2.0.0`. ## Tracking changes [Section titled “Tracking changes”](#tracking-changes) * Human-readable: the [API changelog](/api/changelog/). * Machine-readable: the [change feed](/api/reference/operations/whatschangedsince/) tracks *data* changes (verdicts moving); the [OpenAPI spec](/openapi.yaml) and its `info.version` track *contract* changes. They’re different feeds for different jobs. # The consumer site > How a person uses doesitarm.com — search, the verdict page, alternatives, and the last-checked date. [doesitarm.com](https://doesitarm.com) is the human face of the dataset, and it’s **live today**. No account, no API — you search and you read. ## The flow [Section titled “The flow”](#the-flow) 1. **Search** a title by name (app or game). 2. **Read the verdict** — native, Rosetta 2, a translation layer, or unsupported — with the chip and macOS version it applies to. 3. **Check the date** — every verdict shows when it was last verified, so you can judge how much to trust it. 4. **See alternatives** — if a title is unsupported, the page suggests native equivalents. 5. **Contribute** — submit what happened on your machine; your report becomes a [signal](/overview/how-verdicts-work/) that can update the verdict. ## The same answer, three surfaces [Section titled “The same answer, three surfaces”](#the-same-answer-three-surfaces) What you read on the consumer site is the *same verdict* the [API](/api/) returns and the [MCP server](/api/mcp/) serves — one dataset, three surfaces. The site is the surface for people; the API is the surface for software. If you’re building something, start with the [API overview](/api/). The site is live; the API is Preview Everything on this page describes shipped behavior at doesitarm.com. The API surfaces it links to are documented as a [Preview spec](/api/) and are not built yet. # FAQ > Plain answers about verdicts, freshness, citation, and the API. ## What does `unknown` mean? [Section titled “What does unknown mean?”](#what-does-unknown-mean) It means “Needs more data” — not “broken.” DoesItARM only asserts a positive or a negative on strong evidence; everything else is `unknown`, the honest default. A title stays `unknown` until evidence moves it. See [How verdicts work](/overview/how-verdicts-work/). ## Why is a verdict marked stale? [Section titled “Why is a verdict marked stale?”](#why-is-a-verdict-marked-stale) A compatibility answer decays as apps, games, and macOS change. When a verdict is older than its freshness threshold, it’s flagged `stale: true` and a re-test is queued — but you still get the last known answer. See [Caching & freshness](/api/caching/). ## Why won’t you say something is `unsupported` after one crash? [Section titled “Why won’t you say something is unsupported after one crash?”](#why-wont-you-say-something-is-unsupported-after-one-crash) Because a false “doesn’t run” is the one error that destroys trust. A negative requires a *reproduced* failure; a single flaky crash is held as `unknown` pending another run. We never publish a false negative. ## What happens at the Rosetta 2 deadline? [Section titled “What happens at the Rosetta 2 deadline?”](#what-happens-at-the-rosetta-2-deadline) Rosetta 2 is removed in **macOS 28 (fall 2027)**. Titles that only run through Rosetta will stop working then — verdicts flag this with `breaksAtRosettaEol` so you can plan ahead. IT teams can audit a whole fleet against the deadline via [Apply — Enterprise](/api/access/apply/). ## Can I cite DoesItARM or reuse the data? [Section titled “Can I cite DoesItARM or reuse the data?”](#can-i-cite-doesitarm-or-reuse-the-data) Yes. Verdict facts are published under [CC BY 4.0](/api/citation/) — reuse them with attribution. Agents are encouraged to cite the verdict, the named alternative, and the last-checked date. ## Is there an API? [Section titled “Is there an API?”](#is-there-an-api) It’s a [Preview spec](/api/) — documented as if it works, not yet built. The single-title lookup and search are designed to be [free](/api/rate-limits/); paid plans cover capability like bulk export and the change feed. Start with the [Quickstart](/api/quickstart/). ## How do I report a wrong or missing verdict? [Section titled “How do I report a wrong or missing verdict?”](#how-do-i-report-a-wrong-or-missing-verdict) On the [consumer site](/overview/consumer-site/), submit a report from the title’s page. For the API spec, if a response differs from these docs once you’re an early integrator, that’s drift — flag it via [Free signup](/api/access/free-signup/). # How verdicts work > The mental model behind every answer — status, confidence, basis, signals, freshness — and the Rosetta 2 deadline. DoesItARM is a pipeline: **gather signals → resolve one verdict → serve it everywhere → keep it fresh.** Meet the concepts here; the callable shape is [the Verdict object](/api/verdict/). ## One verdict per title [Section titled “One verdict per title”](#one-verdict-per-title) A title (an app or a game) has exactly **one current verdict** per scope — a (macOS version, chip) pair. Reports and tests are *evidence* that roll up into that one answer; they are not themselves the answer. Agents and IT teams need a single answer, not a thread to interpret. ## Status — the five answers [Section titled “Status — the five answers”](#status--the-five-answers) | Status | Means | Bar to assert | | ------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------- | | `native` | arm64-native on Apple Silicon | strong positive: an arm64 binary that ran, or a high-confidence report | | `rosetta2` | x86\_64, runs translated under Rosetta 2 | strong positive: an x86\_64 binary that ran under Rosetta | | `translation` | runs via a layer (Game Porting Toolkit, CrossOver, Whisky, a VM — named) | strong positive for that layer | | `unsupported` | does not run | **strong negative — a *reproduced* failure, never one flaky run** | | `unknown` | not enough evidence to assert either way | the honest default | The bar is **asymmetric on purpose.** We assert a positive or a negative only when the evidence is strong; everything else is `unknown` (“Needs more data”). A negative needs *reproduced* strong evidence — a single crash is held as `unknown` pending another run — so we **never publish a false negative.** That asymmetry is the trust model. ## Confidence, basis, and signals [Section titled “Confidence, basis, and signals”](#confidence-basis-and-signals) Alongside the status, every verdict carries: * **`confidence`** — `high` / `medium` / `low`. * **`basis`** — *how we know*: `binary` inspection, `automated_test`, `crowd` reports, `vendor` statement, or `curator` note. * **`signals`** — the individual reports and tests that produced the verdict, newest first. The resolver picks the winner by freshness × confidence and surfaces disagreement rather than hiding it. ## Freshness — the moat [Section titled “Freshness — the moat”](#freshness--the-moat) A compatibility answer decays, so every verdict carries **`lastVerified`** and a **`stale`** flag. Re-tests fire on triggers: a new macOS or Game Porting Toolkit release, an app update, a surge of new reports, or a scheduled cadence for popular titles. Freshness is the product’s core promise — see [Caching & freshness](/api/caching/) for how callers read it. ## The Rosetta 2 deadline [Section titled “The Rosetta 2 deadline”](#the-rosetta-2-deadline) Because Rosetta 2 is removed in **macOS 28 (fall 2027)**, a title that only runs *through* Rosetta is living on borrowed time. Verdicts flag this with **`breaksAtRosettaEol`** so a person — or a fleet audit — can plan the migration before the floor disappears. ## Where the data comes from [Section titled “Where the data comes from”](#where-the-data-comes-from) Three sources feed each verdict: **crowdsourced reports** (ProtonDB-style, scales on community), an **automated test harness** *(Preview)* that runs titles on a cloud Apple Silicon fleet, and **known facts** (vendor announcements, binary architecture inspection, Homebrew metadata). DoesItARM never licenses or hosts the software — it gets copies to test cheaply and publishes only the resulting facts. More in [The data we expose](/overview/the-data/). # What DoesItARM is > The canonical, always-fresh source of truth for whether a Mac app or game runs on Apple Silicon — and how. DoesItARM answers one question, authoritatively and currently: **does this Mac app or game run on Apple Silicon — and how?** Not a vague “it should work,” but a specific verdict — runs **natively**, runs through **Rosetta 2**, runs through a **translation layer** (Apple’s Game Porting Toolkit, CrossOver, Whisky, or a VM), or **doesn’t run** — with the macOS version, the chip, the date, and the evidence behind it. ## The problem [Section titled “The problem”](#the-problem) The Mac is in the middle of a forced architecture transition, and the ground keeps moving: * Apple is **removing Rosetta 2 in macOS 28 (fall 2027)**, which breaks 18,800+ Intel-only apps. macOS 27 (fall 2026) is already Apple-Silicon-only. Every Mac user, gamer, and IT team needs to know what survives. * A compatibility answer **decays**. An app ships a native build; a game updates its anti-cheat; a new macOS or Game Porting Toolkit release changes what runs. A blog post from last year is often wrong now. * **AI assistants** increasingly answer “can I run X on my M-series Mac?” — and they need fresh ground truth. Today they fetch DoesItARM’s pages thousands of times a day on users’ behalf, because their training data goes stale. Existing answers are scattered (forum threads, year-old reviews), free-but-static (community wikis), or locked to one surface (a website a human has to read). None is a current, queryable, multi-surface source of truth. ## What DoesItARM is [Section titled “What DoesItARM is”](#what-doesitarm-is) A single fresh dataset of Apple Silicon compatibility verdicts, surfaced three ways: 1. **A free public website** — [doesitarm.com](https://doesitarm.com), live today. Humans and AI crawlers read it. 2. **An agent API / MCP server** — *Preview* — AI assistants and developer tools query it directly for a current verdict instead of scraping a page. See [the API](/api/). 3. **An enterprise readiness product** — *Preview* — IT teams scan their software estate against the Rosetta 2 deadline and get a remediation plan. See [Apply — Enterprise](/api/access/apply/). The data is produced by a **hybrid engine**: crowdsourced reports plus an automated test harness that runs real titles on a cloud Apple Silicon fleet. Freshness is the point — and the moat. See [How verdicts work](/overview/how-verdicts-work/). ## What it is not [Section titled “What it is not”](#what-it-is-not) DoesItARM does not host, sell, stream, or redistribute games or apps. It publishes **facts about** them — compatibility verdicts — which is a different (and far more tractable) business than licensing software, and which is why the verdict data is free to cite under [CC BY 4.0](/api/citation/). # The data we expose > What a verdict contains, where it comes from, and how you're licensed to reuse it. DoesItARM’s product *is* the data: one current compatibility verdict per title, with the evidence and the freshness attached. This page is the plain-language tour; the exact shape is [the Verdict object](/api/verdict/). ## What a verdict contains [Section titled “What a verdict contains”](#what-a-verdict-contains) * **The answer** — `status` (one of native / rosetta2 / translation / unsupported / unknown) and, when it runs through a layer, *which* layer (`translationLayer`). * **How sure we are** — `confidence`, and the `basis` (binary inspection, automated test, crowd reports, vendor statement, curator note). * **The scope** — the `macosVersion` and `chip` the answer applies to. * **The caveats** — human-readable qualifiers like “no online play” or “low FPS”. * **The Rosetta clock** — `breaksAtRosettaEol`, true when the title only survives via Rosetta 2 and will break at macOS 28. * **The freshness** — `lastVerified` and `stale`. * **The receipts** — `signals` (the contributing reports and tests) and `alternatives` (native equivalents when a title is unsupported). ## Where it comes from [Section titled “Where it comes from”](#where-it-comes-from) The [hybrid engine](/overview/how-verdicts-work/) blends crowdsourced reports, an automated test harness on a cloud Apple Silicon fleet *(Preview)*, and known facts (vendor word, binary architecture, Homebrew metadata). DoesItARM tests copies it acquires cheaply and publishes only the **facts** — never the software. ## How you can use it [Section titled “How you can use it”](#how-you-can-use-it) Verdict facts are published under **[Creative Commons Attribution 4.0 (CC BY)](/api/citation/)**. You can reuse them — in an app, a comparison, an AI answer — with attribution to DoesItARM. This is the give-vs-gate line: the **facts are free** (that’s what makes DoesItARM the citable default), and you pay only for **[capability](/api/pricing/)** the free lookup can’t provide — bulk export, the change feed, a freshness SLA, a redistribution license, or enterprise reports. See [Agents & citation](/api/citation/) for the citable unit and the JSON-LD payload. # Who it's for > Mac users checking one app, developers and agents querying programmatically, and IT teams facing the Rosetta 2 deadline. DoesItARM serves three audiences from one dataset. Each reads it a different way. ## Mac users and gamers [Section titled “Mac users and gamers”](#mac-users-and-gamers) You’re about to buy, update, or install something and you want to know: will it run on my Apple Silicon Mac, and how well? Use the [consumer site](/overview/consumer-site/) — search a title, read the verdict, see alternatives if it won’t run. No account, no API. ## Developers and AI agents [Section titled “Developers and AI agents”](#developers-and-ai-agents) You’re building something that needs the answer programmatically — an IDE plugin, an app installer, an “is this compatible?” feature, or an AI assistant answering on a user’s behalf. Query the [API](/api/) for a current, machine-readable [Verdict](/api/verdict/), or wire up the [MCP server](/api/mcp/) so an agent can call it directly. The single lookup and search are [free](/api/rate-limits/). ## IT teams and MSPs [Section titled “IT teams and MSPs”](#it-teams-and-msps) You manage a fleet of Macs and the **Rosetta 2 removal in macOS 28 (fall 2027)** is a hard deadline over thousands of Intel-only apps. You need breadth, monitoring, and a remediation plan — not one lookup at a time. That’s the enterprise readiness product: [Apply — Enterprise](/api/access/apply/) to scan a fleet against the deadline. Buyer ≠ user The person who *feels* the Rosetta pain (an admin) often isn’t the one who *signs* for a fleet scan. The [enterprise door](/api/access/apply/) is free to qualify and routes to a priced pilot — so the admin can start the conversation without a purchase.