Preview VersionThese are pre-release scores, not final grades. Every vendor's full markdown report is published here so the scoring can be checked line by line. A complete rerun follows in roughly 60 days. Found a factual error?

← All platforms

API Report Card · Phone · Methodology v1.1

SimpleVOIP

Preliminary grade
D+ 67/100
33.33 / 50 raw
Evidence tier
Baseline verified
Date run
Sep 10, 2026
Evaluating model
Claude Opus 5
Verification coverage
100%
Live-test battery
Steps 1–5 complete on both surfaces
Checks
27 of 27 scored

Where the points came from.

Five categories, each worth a fixed share of the 100 points. A category earns the fraction of its checks it passes, times its maximum.

Letter grades are absolute, never curved.

The same numeric bands apply to every platform. Nothing here is scored relative to the rest of the board.

A+97-100
A93-96
A−90-92
B+87-89
B83-86
B−80-82
C+77-79
C73-76
C−70-72
D+67-69
D63-66
D−60-62
Fbelow 60

What this means for you.

One paragraph per category, in plain language.

1 · Functional Coverage

13.1 / 15 points

This is the strongest part of the API by a wide margin. Everything a property manager would want to automate about a phone system is reachable: you can read who has an extension and what phone they are on, change where calls go, adjust office hours, and pull complete call history. Two gaps are worth knowing before you plan work. Call queues are not enabled on this cluster, so queue and agent statistics are not available, and the platform's SMS listing endpoint returns a server error, so text history has to come from the webhook feed rather than a query. A third sits on the retention side: nothing lets you delete an individual voicemail message or call recording through the API, so a retention policy has to be run by hand.

2 · Design & Reliability

5.8 / 10 points

The platform API behaves predictably in the ways that matter most for unattended automation. Paging through call history works exactly as documented, you can pull a full dataset as CSV in one request, incremental sync works, and when something fails you get a stable error code and a request id you can quote. Three things will cost you real engineering time. Field types are not dependable: the same call-record timestamp comes back as text in a list and as a number when you fetch that record on its own, so your code has to coerce types rather than trust them. Nothing prevents a duplicate if a create or an SMS send is retried after a timeout. And the vendor's own layer is materially weaker than the platform underneath it: its failures return empty bodies, its responses carry no request id, and the call-record webhooks it sets up for customers are unsigned, meaning anyone who learns your endpoint URL can post fabricated call data to it.

3 · Access Control

1.3 / 5 points

This is the weakest category and the one that should shape how you use the API. You cannot get a read-only key. The credential you hold can change call routing, delete users and delete devices, so any script, contractor or AI agent you hand it to has the power to take your phones down, and nothing in the platform will stop it. There is one key per account, so you cannot give a vendor its own revocable credential, and rotating the key to cut off one integration breaks all of them at once. There is no test environment, so anything you build is developed against live phones. The practical mitigations are yours to build: hold the key in a secret store rather than in code, use a child account's key rather than the parent's so the blast radius stops at one account, and put a read-only wrapper of your own in front of anything you do not fully trust.

4 · Docs & AI-Ready

1.9 / 5 points

A developer can build against this, but not quickly and not with an AI coding assistant doing much of the work. The reference is detailed and free to read, which is more than many vendors offer, and pointing a coding tool at the endpoint pages does work. What you will not get is a specification a tool can consume to generate a working client, a maintained SDK in any language, or any AI-oriented documentation format. Budget for reading the reference by hand, and expect to discover by experiment which documented endpoints your particular cluster actually serves. The most consequential gap is that call detail records, the thing you would most want to pull into reporting, are the least documented object in the API, so the field list has to be derived from live responses.

5 · Access & Cost

11.3 / 15 points

You can get in, and there is no evidence you have to buy up a tier to do it, but you cannot get in today. Both credentials in this assessment took a named human on the vendor's side and about a week each. Plan API work around a lead time measured in weeks rather than an afternoon, and get the credential requested before you need it. Because pricing is not published at all, confirm in writing with your account manager that API use carries no charge on your contract before you build anything that depends on it.

Every check, and why it scored that way.

The same 27 checks are applied to every platform. What changes is which are N-A and what the core objects mean for that kind of software. Each mark below is quoted from the run's own report.

Category 1 · Functional Coverage

13.1 / 15
C1.1

Object coverage

weighted coverage = 92% (27.5 of 30 weight). All five critical objects present with the operations their role requires, live-verified. Deductions: ring groups and queues scored 0.5 because groups is fully present with create, update, and delete verbs while queues returns HTTP 404 on this cluster; SMS scored 0.5 because the platform sms collection returns HTTP 500 datastore_missing_view and the vendor's send endpoint requires separate written authorization; faxes scored 0.5 because faxboxes is fully present while the faxes collection returns HTTP 405. Call detail records were treated as read-appropriate rather than read-only, per the methodology's immutability carve-out for audit records. [Live GET sweep across 21 collections, portal.simplevoip.us:8443/v2, 2026-09-10.]

Yes
C1.2

Core operational actions

weighted coverage = 95% (20 of 21 weight). Documentation-graded, as the operator declined live-data write testing. Create and update paths for users, devices, callflows, voicemail boxes, temporal rules, groups, media, and conferences are documented per-endpoint with worked curl examples and schema tables [docs.2600hz.com/developers/rest/devices-and-users/users; .../call-control/callflows/callflows], and every one of those routes advertised the corresponding verb live. Sending an outbound SMS scored 0.5: the endpoint is documented [Outbound SMS API], but it requires a 10DLC brand and campaign that the vendor sets up, and separate per-account authorization. The authorization requirement is evidenced by the 401 example in the vendor's published Postman collection, which reads, "You have not been authorized to send via this endpoint. Please contact SimpleVoIP support for authorization." The help-center article's own documented error example is different: {"status":"failed","error":"Invalid sender or recipient number provided."}.

Yes
C1.3

Delete or lifecycle actions

weighted coverage = 81% (13 of 16 weight). Documentation-graded. Deletion and disabling are available for all three critical lifecycle changes: users, devices, and call flows, so no critical lifecycle action is absent. Two deductions put it in the 0.50–0.84 band. Deleting a voicemail message or a call recording scored 0.0: no delete operation for either is evidenced anywhere in the packet, the recordings collection advertised OPTIONS, GET only, and the only message route in the reference is a read of the raw audio. Releasing a phone number scored 0.5: it appears only as a documented side effect of enhanced user deletion, never as a direct operation, and the phone_numbers collection advertised GET only.

Partial
C1.4

Change notification

Live query of the system webhook catalogue on this cluster returned 29 hook types, including an object hook covering actions doc_created, doc_edited, and doc_deleted across account, callflow, device, user, vmbox, media, fax, faxbox, mailbox_message, and call_recording document types; a notifications hook exposing 43 event types including new voicemail, missed call, device registration and de-registration, inbound fax, port request, and new user; a dedicated cdr hook; and channel_create, channel_answer, channel_bridge, channel_hold, channel_unhold, and channel_destroy. That covers essentially every critical and important state change in the fixed classification. Efficient incremental polling is independently available and was verified live: modified_from narrowed the full user listing to three records, and created_from and created_to are documented for any collection in Gregorian seconds [.../overview/query-string-filters].

Yes

Category 2 · Design & Reliability

5.8 / 10
C2.1

Modern API conventions

The platform API is resource-oriented REST over JSON with standard verbs, a version in the path, and a consistent /v2/accounts/{ACCOUNT_ID}/{resource}/{RESOURCE_ID} structure [.../overview/api-basics, Basic URI Structure]. Verified live across 21 collections. Disclosed limitation: the vendor's own customer API is RPC-shaped rather than resource-oriented — its bulk endpoints act on no resource identifier and the vendor describes it in its own words as "a REST-like API" [Time of Day Bulk Change API].

Yes
C2.2

Consistent typing

Core fields are stringly typed and types vary across endpoints. Live-observed on 2026-09-10: in the CDR list view the timestamp field is a JSON string, while the single-record view of the same CDR returns timestamp as an integer. Also in the list view, cost, rate, unix_timestamp, and unix_timestamp_micro are strings while billing_seconds and duration_seconds are integers in the same record. The vendor's own CDR webhook documentation declares timestamp as JSON type int, which the list endpoint contradicts [Call Detail Record (CDR) Webhooks, Webhook Payload Structure]. On the customer API, time-of-day rules read back as strings such as "09:00" under day-named keys, but are written as integers in seconds past midnight under entirely different key names, so a read cannot be round-tripped into a write [Time of Day Bulk Change API, Rule Objects]. The webhook documentation separately warns that the default form-data delivery format results in "integers (like timestamps) being encoded as strings."

No
C2.3

Structured errors

The platform API is close to exemplary: every failure returned a consistent envelope carrying a populated, stable machine token in message, a human-readable string in data.message, the HTTP status echoed in error, and a request_id. Live-observed tokens include invalid_credentials (401), bad_identifier (404), not_found (404), invalid_method (405), and datastore_missing_view (500), each with the correct HTTP status. Two findings hold it to partial. First, a malformed query filter returned HTTP 200 with "status": "success" and an empty data array rather than an error, so a filter typo silently reads as "no matching records." Second, the vendor's own customer API has no structured errors at all: an invalid Bearer token and a missing Authorization header each returned HTTP 401 with a zero-byte body and Content-Type: text/html, and an unknown path returned HTTP 404 with an empty body. A nonexistent recording identifier returned HTTP 500 where the vendor's published documentation specifies a 404 "No Recording Found" response.

Partial
C2.4

Duplicate prevention

Documentation-graded; no write was issued. Neither surface documents idempotency keys, and a search of the developer documentation and the 300-path swagger specification returned zero occurrences of idempotency, If-Match, or ETag parameters. The check expressly carves out operations that are naturally idempotent, so the fact that POST and PATCH updates set a document to a stated value is not protection, it is exclusion from the requirement. What remains after that carve-out is unprotected: collection-level PUT creates produce a duplicate record on retry, POST /sms/send sends a second message, and the vendor's bulk endpoints enqueue a fresh batch of jobs on every call, returning a new enqueued_tasks count each time. Client-set entity IDs exist but sit behind a system feature flag with no evidence it is enabled here.

No
C2.5

Graceful handling under load

A 429 response is documented, together with the token-bucket mechanism keyed on client IP and account ID [.../sys-admin/rate-limiting]. What is missing is usable recovery guidance. No Retry-After header and no rate-limit response headers were observed on any call. The only numbers published are administrator-configurable defaults, hedged as what "typically" happens and presented on a page written for the platform operator rather than the API consumer, and per-endpoint token costs are themselves tunable. The one live signal the API exposes, a tokens object in the response envelope, read remaining: 0 on authenticated reads that nonetheless succeeded, so an integration cannot pace itself from it. The customer API documents no throttling at all and returned no rate-limit headers.

Partial
C2.6

Pagination for large collections

Live-verified. A CDR request with page_size=5 returned exactly five records plus start_key, next_start_key, and page_size. Requesting the second page with the returned next_start_key produced five further records with zero overlapping identifiers and echoed the requested key back as that page's start_key. The documentation states that a missing next_start_key indicates the last page, gives the ordering default as descending with ascending=true available, and states the stability condition, "Assuming no changes are made to the underlying documents, start_key will get you this page of results" [.../overview/api-basics, Pagination].

Yes
C2.7

Bulk or incremental export

Live-verified on three independent mechanisms. A single request with Accept: text/csv returned 501 CSV rows and 326 KB of call history in one response. paginate=false returned the complete user collection unpaginated. modified_from narrowed the full user listing to three records, demonstrating working incremental sync. Chunked responses are additionally documented for large datasets, on by default for CDR interaction and ledger endpoints [.../overview/api-basics, Chunked Response].

Yes
C2.8

Webhook security and delivery reliability

The platform mechanism alone would earn a yes: payloads can be signed with HMAC-SHA256 through security_settings.sha256_key, with the exact construction published as base64_encode(hmac(SHA256Key, TimestampString + DataJSON)) and a worked example; timestamps are included on all payloads and the documentation states this is to "prevent replay attacks"; retries is a first-class field bounded 0 to 4 and defaulting to 2; failing hooks are auto-disabled and surface a disable_reason; and a webhook_attempts resource records delivery history [.../webhooks/webhooks, Hook Security]. What holds this to partial is that the vendor's own webhooks — the CDR and SMS feeds SimpleVoIP provisions for customers and documents in its help center — are unsigned by the vendor's own admission: "We currently don't support authentication on webhook POST requests. Mention this to your account manager if you would like to see this implemented!" [Call Detail Record (CDR) Webhooks, FAQ]. No retry policy is documented for those either. The vendor ships both a secured mechanism and an unsecured one, and its own support articles route customers to the unsecured one.

Partial
C2.9

Concurrency and conflict control

The mechanism exists and was observed live: a single-entity GET returned ETag: "22-61b6..." matching a revision field in the response envelope, and the API advertises if-match in access-control-allow-headers and etag in access-control-expose-headers. What is missing is the documentation half: a targeted first-party search across both 2600Hz domains, plus a scan of the developer documentation and the swagger specification, found no documented conflict semantics, no documented 409 behaviour, and no documented concurrency limits. The capability is discoverable only by inspecting responses.

Partial
C2.10

Versioning and backward compatibility

An explicit version identifier is present in the path and documented as the only supported value [.../overview/api-basics], and the running build is reported in every response envelope. One breaking-changes document exists, covering the Kazoo 5.1 to 5.3 transition in field-level detail [.../changelog/kazoo-51-53-breaking-changes]. What is absent is a backward-compatibility policy defining breaking versus non-breaking changes, and any deprecation window or notice commitment. The gap is concrete rather than theoretical: the cluster serving this operator reported version 5.4.7.25 in every response, and no published change record covers 5.4 at all.

Partial
C2.11

Request traceability

On the platform API this is a clear strength, verified on every single call including all four deliberate errors: an x-request-id response header and a matching request_id in the body envelope, documented as "ID of the request; usable for debugging the server-side processing of the request" [.../overview/api-basics, Response Envelope]. On the vendor's own customer API there is no request identifier of any kind — live header capture across successful and failed calls returned only Date, Server, X-Powered-By, and cache headers. A customer reporting a problem on that surface has nothing to quote.

Partial
C2.12

Service availability and status transparency

SimpleVoIP publishes a public status page listing named components with current state, a past-incidents section, and 90-day uptime tracking; its incident-history feed contains multiple real prior incidents including regional connectivity events and planned hardware migrations [status.simplevoip.us and /history.atom, retrieved 2026-09-10]. A published SLA commits to "99.99% availability each month of our hosted VoIP platform" with a one-day service credit per whole hour of unavailability below that, and describes the three-datacenter architecture behind it [SimpleVoIP Service Level Agreement]. Disclosed limitation: both the status components and the SLA cover voice, portal, and application services rather than the APIs specifically.

Yes

Category 3 · Access Control

1.3 / 5
C3.1

Read-only credentials

The upstream platform documents both a crossbar:read_only scope and a token_restrictions mechanism capable of restricting a token to specific HTTP methods and accounts [.../authentication/scope-restrictions; .../authentication/token-restrictions]. Neither is available on SimpleVoIP's cluster: live requests to the token-restrictions route returned HTTP 404 bad_identifier at both account and user level, and the scope-restrictions route returned HTTP 404 not_found. The single credential issued to this operator carries write access to every route it can reach. The operator states no read-only credential was offered for either surface.

No
C3.2

Scoped credentials

Coarse scoping exists and was verified: each account in the tree holds its own API key, and the child account exposed a distinct key of its own, so an operator can choose a credential bounded to a lower account rather than the parent. That is the extent of it. The parent credential under test reached the parent account record, its children and descendants listing, the full record set of the child account, and the parent account's own API key value. No restriction by resource, by action, or by role was available, for the reasons cited in C3.1.

Partial
C3.3

Multiple keys

An account holds exactly one API key; the documented retrieval route returns a single api_key value and no route exists to issue an additional credential for the same account [.../authentication/account-api-authentication]. Two integrations against the same account must therefore share one key, which means neither can be revoked without breaking the other. Per-account keys in a parent-child tree are an account-structure artefact, not an integration-credential mechanism.

No
C3.4

Rotation and revocation

Self-serve rotation is documented for the platform surface, and this corrects an error in the first grading pass of this report. The account reference carries a section headed "Re-create the account's API key," stating that "If you think that your account's API key might be exposed you can create a new one with the api_key endpoint. Issuing a PUT request to this endpoint will generate a new API key for the account and will return the new key in response," gated on an admin token [.../account-actions-and-permissions/accounts]. The route advertised PUT live; it was deliberately not executed, since doing so would have invalidated the operator's working credential. Held to partial for two reasons. The customer API Bearer token has no documented rotation or revocation path at all and is reissued by the engineering team through an account manager. And because there is exactly one key per account, rotating is all-or-nothing: it cuts off every integration at once rather than the one you meant to revoke.

Partial
C3.5

Test and production isolation

No sandbox or separate test environment exists for SimpleVoIP customers. Help-center searches for sandbox, test account, trial, and developer account returned no such offering; the 2600Hz documentation sitemap contains no sandbox pages, and its single trial-account page concerns 2600Hz's own hosted trial for testing a different product rather than an environment available to a SimpleVoIP customer. Per the check's own instruction, this is excluded from the math rather than scored zero.

N-A

Category 4 · Docs & AI-Ready

1.9 / 5
C4.1

Complete self-serve reference

The platform reference is publicly accessible with no login and is genuinely example-rich: 123 developer pages carrying per-endpoint curl request and response examples plus schema tables giving key, description, type, default, and required status. What holds it to partial is that it documents the upstream platform rather than SimpleVoIP's deployment, and nothing first-party tells a SimpleVoIP customer which parts apply to them. Four documented endpoints behaved differently on the live cluster: queues returned 404, sms returned 500, about returned 403, and the documented per-resource schema route returned 404 for the CDR schema. The resource a property manager most needs is the least documented: call detail records have no schema in the live schemas catalogue, no definition in the swagger file, and return 35 fields in the list view versus 71 in the single-record view, with the extra fields described nowhere. On the vendor's own surface, the published Postman collection contains two entries with no method, no URL, and no example — "Fetch Media IDs by account" and "Password Reset" — and its Mobile endpoints reference a {{provisioning_api_url}} base variable that the collection never defines, though the host is recoverable by reading it out of the saved example request URLs.

Partial
C4.2

Reliable machine-consumable integration path

Three candidate mechanisms exist and none is complete. A Swagger 2.0 specification carrying 300 paths and 783 definitions is present in 2600Hz's repository, but it is not fit for code or tool generation as published: every operation declares only {"200": {"description": "request succeeded"}} with no response schema and no error responses, host is the placeholder localhost:8000, there is no cdr definition at all, and it is neither published on nor referenced from the documentation site. 2600Hz's own engineering documentation warns that the generator "would maybe result in generating outdated JSON schema files and Swagger file." The official SDK page is banner-marked as covering a Kazoo version that "is no longer supported," lists "PHP" with no link, and has an empty community section. No MCP server was evidenced. The one genuine strength is a live schemas endpoint, which returned 492 JSON Schemas on this cluster and gives real machine-readable data models — but schemas alone carry no paths or methods, so they cannot generate a client on their own.

Partial
C4.3

AI-readable documentation

Neither llms.txt nor llms-full.txt exists on either docs.2600hz.com or simplevoip.com; all four requests returned 404. Probes for .md and .txt variants of documentation pages returned 404. No downloadable documentation corpus was evidenced. SimpleVoIP's own API documentation consists of Zendesk help-center articles and a client-rendered Postman page, neither structured for reliable retrieval — the Postman page in particular returns only an empty shell to a non-browser client, and its content had to be recovered from a separate JSON endpoint.

No
C4.4

Kept current

Currency signals exist but are stale and irregular, and the staleness is specific to the API rather than to the vendor's documentation generally. Across all 123 developer pages, none carries a last-modified date later than mid-2025, and the tail reaches back to 2016. The only changelog stops at Kazoo 5.3 while the cluster serving this operator reports 5.4.7.25 in every response, so the running version has no published change record. SimpleVoIP's release notes stop at Sprint 108, released 2 September 2025 — a year before this assessment — even though its help center is otherwise actively maintained, with its newest article created 26 August 2026. Its three API articles were last updated December 2022, August 2024, and July 2025.

Partial

Category 5 · Access & Cost

11.3 / 15
C5.1

Self-serve API key

Split evidence across the two surfaces. The platform key is self-serve once a portal login exists: the vendor's engineer states in writing that "to find your Account API key, you may find it in Authentication -> API Key Authentication -> API Key Value," and the operator confirms retrieving it that way. But the prerequisite portal login was not self-serve, taking a project manager and roughly a week to obtain. The customer API key is not self-serve at any stage — the vendor's own published article states, "You will also need an API key provided by the SimpleVoIP Engineering team. These are available upon request. Please reach out to your account manager to initiate this process" [Time of Day Bulk Change API, Prerequisites], and the operator reports that token likewise required a project manager and about a week. Sending SMS requires a further approval step beyond the key, evidenced by the vendor's own documented rejection message directing the caller to contact support for authorization.

Partial
C5.3

Not commercially gated

No first-party material conditions API access on a plan tier, and the plans page does not mention API access at all [simplevoip.com/features-and-plans/]. The operator's own record is affirmative rather than merely silent: working credentials for both surfaces were issued against their existing account, with no plan upgrade involved and no charge for API access stated to them. The 10DLC brand and campaign required before sending SMS is carrier-mandated regulatory registration, which this check expressly excludes from counting as commercial gating. Chargeable engineering hours for bespoke webhook customization are custom development work, not a gate on the documented API. Disclosed limitation: SimpleVoIP publishes no pricing for any tier, so this rests on the absence of any evidenced gate plus one operator's live experience rather than on a published entitlement statement.

Yes

What works

  • A public status page with incident history and 90-day uptime, plus a published 99.99% SLA
  • Full call history as CSV in a single request, 501 rows pulled live
  • Cursor pagination verified live across pages with no overlap and a documented stability rule
  • Incremental sync works: a modified-since filter narrowed a full user listing live
  • A request id on every response, in both header and body, including on every deliberate error
  • Stable machine-readable error codes on the platform API, observed across five failure classes
  • 29 webhook types covering essentially every state change the phone system makes
  • HMAC-SHA256 webhook signing with a published construction and bounded retries
  • Extensions, phones, routing, office hours and call history are all reachable from code
  • No plan tier gates API access, confirmed against the operator's own account

What to watch

  • No read-only credential: the documented scope mechanism returns 404 on this cluster
  • One key per account, so two integrations share it and neither can be revoked alone
  • No sandbox or test environment, so everything is built against live phones
  • The same call-record timestamp is a string in a list and a number when fetched on its own
  • No idempotency anywhere, so a retried create or SMS send duplicates
  • The vendor's own call-record webhooks are unsigned, by its own admission in a help article
  • The vendor's customer API returns empty error bodies and carries no request id
  • Both credentials took a project manager and about a week each to obtain
  • API documentation last updated between 2022 and 2025, while the live cluster is a version ahead
  • Call detail records, the most useful object here, have no published schema anywhere

The bottom line for a property manager

You can build real automation on this today, and the useful half of it is not SimpleVoIP's engineering, it is the 2600Hz platform underneath, which SimpleVoIP operates and points you at. Through it you can read your full call history, page and export it reliably, keep extensions and phones in step with staffing, change call routing and office hours in code, and subscribe to webhooks covering essentially every change the phone system makes. SimpleVoIP's own thin layer on top adds bulk hours changes across many sites and outbound texting, but is noticeably rougher: empty error bodies, no request identifiers, and call-record webhooks the vendor confirms are unauthenticated, so treat anything arriving on that endpoint as unverified input. The two things that should govern your plans are access control and lead time. There is no read-only key, no way to scope a credential to a single action, one key per account, and no test environment, which together mean any credential you issue can delete users and re-route calls against live phones. Keep the key in a secret store, prefer a lower account's key over the parent's, and put your own read-only wrapper in front of anything you would not trust with the phone system. Separately, both credentials in this assessment took a project manager and about a week, so request access well before you need it and confirm in writing that it carries no charge, since no pricing is published. This is a phone system with a usable API, not a system of record. It does not touch tenant ledgers, deposits or trust accounting. Its property-management value is as a data source and a control surface alongside your property management system: call history for response-time reporting and staff accountability, and routing changes driven by your own calendar or staffing data rather than by hand. The 67 reflects excellent functional reach dragged down hard by weak credential controls, thin machine-readable documentation, and API documentation that has gone a year or more without an update while the platform it describes has moved on a full minor version. Three independent graders working from the same frozen evidence each arrived at 65 before reconciliation, so treat the grade band rather than the exact number as the finding.

Check it yourself.

Both files behind this page, in full.

SimpleVOIP’s full report

The complete markdown report this page is built from, including the evidence packet, the run metadata and every check in full.

Download the SimpleVOIP report

The grading file

The exact rubric behind every score on this page. Same file, every platform. Run it yourself and compare.

Download the methodology

Found a factual error in your grade?

Tell us and we will fix it. Every mark on this page traces to a specific piece of first-party evidence or a live API call, and the full report is published so you can see exactly what was checked and what it was checked against.

Confirmed factual errors are corrected immediately.

Everything else waits. We do not rescore piecemeal on request, because a board where some vendors have been re-run and others have not is not a fair comparison. Shipped improvements, changed documentation and disagreements about judgement all go into the next full rerun.

Contact us with a factual error