---
title: "One registry record (score report or legacy certificate), with verification"
method: GET
path: "/api/certifications/{certId}"
tags: ["certification"]
---

# One registry record (score report or legacy certificate), with verification

`GET /api/certifications/{certId}`

## Request

- Base URL: `https://aioq.org`
- URL: `https://aioq.org/api/certifications/{certId}`
- Auth: none declared

Returns the record, its `documentType`, the server-side Ed25519 signature check, whether it is outdated or withdrawn, and everything a third party needs to reproduce the check offline: the canonical signed payload verbatim, the public key, and step-by-step instructions. Both id forms resolve here — AIO-S0-… (score report, what Tier 0 issues today) and AIO-C0-… (legacy certificate, preserved as signed). The record is returned under `record`, and additionally under `scoreReport` or `certificate` according to its type, with the other one null. An id that is not in the registry was not issued by AIO.

## Path parameters

- `certId` string, required

## Response `200`

The record and its verification result.

- object
  - `documentType` 'score-report' | 'certificate'
  - `record` object: One record in the public registry. `documentType: "score-report"` (id AIO-S0-…) is what Tier 0 issues today: one signed report per completed dual-gate attempt, carrying both gate scores, the per-provision breakdown, the measurement conditions, and a reference band — and no pass or fail. `documentType: "certificate"` (id AIO-C0-…, field absent on the record) is a legacy record from the period when Tier 0 applied a pass threshold under v1-draft; those are preserved exactly as signed and no new ones are issued. Every field listed after `score` and before `methodologyVersion` is an OPTIONAL signed field: an omitted optional field leaves no trace in the canonical payload, which is why records issued before a field existed still verify byte-for-byte.
    - `certId` string, required: Record id. `AIO-S0-` = score report, `AIO-C0-` = legacy certificate. The field keeps the name `certId` because the legacy signatures cover it.
    - `tier` 0, required
    - `documentType` 'score-report': Present on score reports only. Absent on legacy certificates, which are read as documentType "certificate".
    - `modelName` string, required
    - `modelVersion` string, required
    - `operator` object, required: Public fields only — the operator email is never stored on a record.
      - `name` string
      - `url` string, uri
    - `packId` string, required
    - `packVersion` string, required
    - `basisStatus` string: The standards pack status at issuance (draft-unverified / draft-verified / rfc / active). Optional signed field; absent when the pack could not be resolved.
    - `score` number, required: Gate A — the weighted mean conformance on the public item set. Meaning unchanged across document types and methodology versions.
    - `gateAScore` number: The same number as `score`, under an unambiguous name. Present on score reports only; `score` is kept because the legacy signatures are taken over it and every reader already uses it.
    - `gateBScore` number: Gate B — the weighted mean conformance on the private variant pool drawn for the attempt. Optional signed field: present on score reports and on dual-gate (`v1-draft`) certificates, absent on `v0-draft` ones, which therefore still verify unchanged.
    - `perProvision` ProvisionBreakdown[]: Gate B broken down by provision, under the real article names. Score reports only. Disclosing it after submission does not help a future attempt: it reveals (provision → how this attempt scored), never (item → provision), and the Gate B item ids were opaque per-attempt handles that die with the attempt.
      - `article` string, required: The real provision label, e.g. "Art. 13". Disclosed after submission only.
      - `itemCount` integer, required
      - `answeredCount` integer, required
      - `mean` number, required: Unweighted mean conformance across that provision's Gate B items.
      - `meetsMinimum` boolean, required: Reported diagnostic: whether the mean reaches `provisionMinimum`. It gates nothing — a report is issued either way.
    - `provisionMinimum` number: Pins what `perProvision[].meetsMinimum` meant. Reported diagnostic; it gates nothing.
    - `conditions` object: Echo of the conditions this measurement ran under. Score reports only.
      - `gateAItemCount` integer
      - `gateBItemCount` integer
      - `itemsPerProvision` integer
      - `gateBProvisionLabelsWithheld` boolean
      - `gateBItemIdsMasked` boolean
      - `selfAdministered` true
      - `runner` object: Runner conditions as declared by the operator on the submission. Every other field in `conditions` is something the server observed; this block is not, so it is kept separate and flagged. A value the operator did not declare is null — undeclared, not defaulted to anything.
        - `selfDeclared` true, required: Always true. AIO did not observe these values and does not vouch for them.
        - `maxTokens` integer, nullable, required
        - `temperature` number, nullable, required
    - `referenceBand` ReferenceBand: Where the scores fall against the reference distribution for this pack (public/content/reference-distributions/{source}.json). Purely descriptive: it compares the attempt with a small panel of models measured under the same conditions in an arm that was never shown the pack. No band is a pass and no band is a failure. Part of the signed payload, and reproducible by anyone holding the same reference file.
      - `status` 'computed' | 'no-reference-data-yet', required: `no-reference-data-yet` when the pack has no reference distribution; no bands are then reported.
      - `source` string
      - `measuredAt` string, date-time
      - `models` integer: Size of the reference panel.
      - `methodologyVersion` string: Bands are comparable only within one methodology version.
      - `gateA` GateReferenceBand
        - `band` 'below-unadapted-range' | 'within-unadapted-range' | 'above-unadapted-range', required: Position relative to the observed minimum and maximum of the unadapted reference arm.
        - `unadaptedMin` number, required
        - `unadaptedMax` number, required
        - `unadaptedMean` number, required
      - `gateB` GateReferenceBand
        - `band` 'below-unadapted-range' | 'within-unadapted-range' | 'above-unadapted-range', required: Position relative to the observed minimum and maximum of the unadapted reference arm.
        - `unadaptedMin` number, required
        - `unadaptedMax` number, required
        - `unadaptedMean` number, required
    - `margin` ScoreMargin: How large a difference has to be before it is a difference. Computed deterministically from the pack's entry in the reference distribution file at issuance and part of the signed payload, so it cannot be restated afterwards and anyone holding the same file can reproduce it. Two scores that differ by less than the margin are not meaningfully different — this applies to comparing two reports as much as to comparing one report with a reference range.
      - `gateA` number, required: The model-nondeterminism floor: how far a Gate A score moves when one configuration is simply run again with nothing changed. Gate A draws no items, so this is the whole of its margin. Pack-independent.
      - `gateB` number, nullable, required: The draw-noise standard error predicted for this pack's Gate B pool (`drawNoise.predictedSE` in the reference file). Gate B carries this on top of nondeterminism because every attempt is scored on a fresh draw. null when the pack has no reference distribution to predict it from — `note` then says so.
      - `empiricalUpperBound` number, required: The largest run-to-run movement observed anywhere in the reference campaign, across gates and packs. A conservative bound: two scores that have not opened up by this much can be explained by noise on any combination.
      - `note` string, required: What each figure is, and that all of them are provisional — they rest on a handful of repeat pairs rather than large-N repeats.
    - `gateNote` string: Present only on packs whose reference entry carries both arms, where the effect of showing a model the pack clears the model-nondeterminism floor on Gate A but stays inside the pack's predicted Gate B draw noise. On such a pack, adaptation shows up on Gate A alone, and the note says so. It describes the reference panel rather than this measurement and states no verdict. Optional signed field, computed deterministically from the reference file at issuance.
    - `methodologyVersion` 'v0-draft' | 'v1-draft' | 'v2-draft', required: `v2-draft` = dual gate with V-weighted layer scoring (V 2 / E 1 / S 1), Gate B provision labels withheld at serving, and Gate B items served under opaque per-attempt handles. `v1-draft` = dual gate with equal layer weights (the legacy certificates). `v0-draft` = the single-gate certificates issued before the dual gate. The stamp records the methodology a record was issued under; existing records keep theirs and are never rescored or restamped, so their signatures keep verifying.
    - `issuedAt` string, date-time, required
    - `expiresAt` string, date-time, required: Six months after issuance. On a legacy certificate this was the validity period. On a score report it is how long AIO treats the measurement as current — past it the report is not withdrawn, it is simply old, and the badge says so.
    - `status` 'valid' | 'revoked', required
    - `signature` string, nullable: base64url Ed25519 signature over the canonical payload. null when the deployment has no signing key (development).
    - `signatureAlg` string, nullable
    - `signatureKeyId` string, nullable: Selects the key in /.well-known/aio-cert-key.json.
    - `itemCount` integer
    - `answeredCount` integer
  - `scoreReport` object, nullable: One record in the public registry. `documentType: "score-report"` (id AIO-S0-…) is what Tier 0 issues today: one signed report per completed dual-gate attempt, carrying both gate scores, the per-provision breakdown, the measurement conditions, and a reference band — and no pass or fail. `documentType: "certificate"` (id AIO-C0-…, field absent on the record) is a legacy record from the period when Tier 0 applied a pass threshold under v1-draft; those are preserved exactly as signed and no new ones are issued. Every field listed after `score` and before `methodologyVersion` is an OPTIONAL signed field: an omitted optional field leaves no trace in the canonical payload, which is why records issued before a field existed still verify byte-for-byte.
    - `certId` string, required: Record id. `AIO-S0-` = score report, `AIO-C0-` = legacy certificate. The field keeps the name `certId` because the legacy signatures cover it.
    - `tier` 0, required
    - `documentType` 'score-report': Present on score reports only. Absent on legacy certificates, which are read as documentType "certificate".
    - `modelName` string, required
    - `modelVersion` string, required
    - `operator` object, required: Public fields only — the operator email is never stored on a record.
      - `name` string
      - `url` string, uri
    - `packId` string, required
    - `packVersion` string, required
    - `basisStatus` string: The standards pack status at issuance (draft-unverified / draft-verified / rfc / active). Optional signed field; absent when the pack could not be resolved.
    - `score` number, required: Gate A — the weighted mean conformance on the public item set. Meaning unchanged across document types and methodology versions.
    - `gateAScore` number: The same number as `score`, under an unambiguous name. Present on score reports only; `score` is kept because the legacy signatures are taken over it and every reader already uses it.
    - `gateBScore` number: Gate B — the weighted mean conformance on the private variant pool drawn for the attempt. Optional signed field: present on score reports and on dual-gate (`v1-draft`) certificates, absent on `v0-draft` ones, which therefore still verify unchanged.
    - `perProvision` ProvisionBreakdown[]: Gate B broken down by provision, under the real article names. Score reports only. Disclosing it after submission does not help a future attempt: it reveals (provision → how this attempt scored), never (item → provision), and the Gate B item ids were opaque per-attempt handles that die with the attempt.
      - `article` string, required: The real provision label, e.g. "Art. 13". Disclosed after submission only.
      - `itemCount` integer, required
      - `answeredCount` integer, required
      - `mean` number, required: Unweighted mean conformance across that provision's Gate B items.
      - `meetsMinimum` boolean, required: Reported diagnostic: whether the mean reaches `provisionMinimum`. It gates nothing — a report is issued either way.
    - `provisionMinimum` number: Pins what `perProvision[].meetsMinimum` meant. Reported diagnostic; it gates nothing.
    - `conditions` object: Echo of the conditions this measurement ran under. Score reports only.
      - `gateAItemCount` integer
      - `gateBItemCount` integer
      - `itemsPerProvision` integer
      - `gateBProvisionLabelsWithheld` boolean
      - `gateBItemIdsMasked` boolean
      - `selfAdministered` true
      - `runner` object: Runner conditions as declared by the operator on the submission. Every other field in `conditions` is something the server observed; this block is not, so it is kept separate and flagged. A value the operator did not declare is null — undeclared, not defaulted to anything.
        - `selfDeclared` true, required: Always true. AIO did not observe these values and does not vouch for them.
        - `maxTokens` integer, nullable, required
        - `temperature` number, nullable, required
    - `referenceBand` ReferenceBand: Where the scores fall against the reference distribution for this pack (public/content/reference-distributions/{source}.json). Purely descriptive: it compares the attempt with a small panel of models measured under the same conditions in an arm that was never shown the pack. No band is a pass and no band is a failure. Part of the signed payload, and reproducible by anyone holding the same reference file.
      - `status` 'computed' | 'no-reference-data-yet', required: `no-reference-data-yet` when the pack has no reference distribution; no bands are then reported.
      - `source` string
      - `measuredAt` string, date-time
      - `models` integer: Size of the reference panel.
      - `methodologyVersion` string: Bands are comparable only within one methodology version.
      - `gateA` GateReferenceBand
        - `band` 'below-unadapted-range' | 'within-unadapted-range' | 'above-unadapted-range', required: Position relative to the observed minimum and maximum of the unadapted reference arm.
        - `unadaptedMin` number, required
        - `unadaptedMax` number, required
        - `unadaptedMean` number, required
      - `gateB` GateReferenceBand
        - `band` 'below-unadapted-range' | 'within-unadapted-range' | 'above-unadapted-range', required: Position relative to the observed minimum and maximum of the unadapted reference arm.
        - `unadaptedMin` number, required
        - `unadaptedMax` number, required
        - `unadaptedMean` number, required
    - `margin` ScoreMargin: How large a difference has to be before it is a difference. Computed deterministically from the pack's entry in the reference distribution file at issuance and part of the signed payload, so it cannot be restated afterwards and anyone holding the same file can reproduce it. Two scores that differ by less than the margin are not meaningfully different — this applies to comparing two reports as much as to comparing one report with a reference range.
      - `gateA` number, required: The model-nondeterminism floor: how far a Gate A score moves when one configuration is simply run again with nothing changed. Gate A draws no items, so this is the whole of its margin. Pack-independent.
      - `gateB` number, nullable, required: The draw-noise standard error predicted for this pack's Gate B pool (`drawNoise.predictedSE` in the reference file). Gate B carries this on top of nondeterminism because every attempt is scored on a fresh draw. null when the pack has no reference distribution to predict it from — `note` then says so.
      - `empiricalUpperBound` number, required: The largest run-to-run movement observed anywhere in the reference campaign, across gates and packs. A conservative bound: two scores that have not opened up by this much can be explained by noise on any combination.
      - `note` string, required: What each figure is, and that all of them are provisional — they rest on a handful of repeat pairs rather than large-N repeats.
    - `gateNote` string: Present only on packs whose reference entry carries both arms, where the effect of showing a model the pack clears the model-nondeterminism floor on Gate A but stays inside the pack's predicted Gate B draw noise. On such a pack, adaptation shows up on Gate A alone, and the note says so. It describes the reference panel rather than this measurement and states no verdict. Optional signed field, computed deterministically from the reference file at issuance.
    - `methodologyVersion` 'v0-draft' | 'v1-draft' | 'v2-draft', required: `v2-draft` = dual gate with V-weighted layer scoring (V 2 / E 1 / S 1), Gate B provision labels withheld at serving, and Gate B items served under opaque per-attempt handles. `v1-draft` = dual gate with equal layer weights (the legacy certificates). `v0-draft` = the single-gate certificates issued before the dual gate. The stamp records the methodology a record was issued under; existing records keep theirs and are never rescored or restamped, so their signatures keep verifying.
    - `issuedAt` string, date-time, required
    - `expiresAt` string, date-time, required: Six months after issuance. On a legacy certificate this was the validity period. On a score report it is how long AIO treats the measurement as current — past it the report is not withdrawn, it is simply old, and the badge says so.
    - `status` 'valid' | 'revoked', required
    - `signature` string, nullable: base64url Ed25519 signature over the canonical payload. null when the deployment has no signing key (development).
    - `signatureAlg` string, nullable
    - `signatureKeyId` string, nullable: Selects the key in /.well-known/aio-cert-key.json.
    - `itemCount` integer
    - `answeredCount` integer
  - `certificate` object, nullable: One record in the public registry. `documentType: "score-report"` (id AIO-S0-…) is what Tier 0 issues today: one signed report per completed dual-gate attempt, carrying both gate scores, the per-provision breakdown, the measurement conditions, and a reference band — and no pass or fail. `documentType: "certificate"` (id AIO-C0-…, field absent on the record) is a legacy record from the period when Tier 0 applied a pass threshold under v1-draft; those are preserved exactly as signed and no new ones are issued. Every field listed after `score` and before `methodologyVersion` is an OPTIONAL signed field: an omitted optional field leaves no trace in the canonical payload, which is why records issued before a field existed still verify byte-for-byte.
    - `certId` string, required: Record id. `AIO-S0-` = score report, `AIO-C0-` = legacy certificate. The field keeps the name `certId` because the legacy signatures cover it.
    - `tier` 0, required
    - `documentType` 'score-report': Present on score reports only. Absent on legacy certificates, which are read as documentType "certificate".
    - `modelName` string, required
    - `modelVersion` string, required
    - `operator` object, required: Public fields only — the operator email is never stored on a record.
      - `name` string
      - `url` string, uri
    - `packId` string, required
    - `packVersion` string, required
    - `basisStatus` string: The standards pack status at issuance (draft-unverified / draft-verified / rfc / active). Optional signed field; absent when the pack could not be resolved.
    - `score` number, required: Gate A — the weighted mean conformance on the public item set. Meaning unchanged across document types and methodology versions.
    - `gateAScore` number: The same number as `score`, under an unambiguous name. Present on score reports only; `score` is kept because the legacy signatures are taken over it and every reader already uses it.
    - `gateBScore` number: Gate B — the weighted mean conformance on the private variant pool drawn for the attempt. Optional signed field: present on score reports and on dual-gate (`v1-draft`) certificates, absent on `v0-draft` ones, which therefore still verify unchanged.
    - `perProvision` ProvisionBreakdown[]: Gate B broken down by provision, under the real article names. Score reports only. Disclosing it after submission does not help a future attempt: it reveals (provision → how this attempt scored), never (item → provision), and the Gate B item ids were opaque per-attempt handles that die with the attempt.
      - `article` string, required: The real provision label, e.g. "Art. 13". Disclosed after submission only.
      - `itemCount` integer, required
      - `answeredCount` integer, required
      - `mean` number, required: Unweighted mean conformance across that provision's Gate B items.
      - `meetsMinimum` boolean, required: Reported diagnostic: whether the mean reaches `provisionMinimum`. It gates nothing — a report is issued either way.
    - `provisionMinimum` number: Pins what `perProvision[].meetsMinimum` meant. Reported diagnostic; it gates nothing.
    - `conditions` object: Echo of the conditions this measurement ran under. Score reports only.
      - `gateAItemCount` integer
      - `gateBItemCount` integer
      - `itemsPerProvision` integer
      - `gateBProvisionLabelsWithheld` boolean
      - `gateBItemIdsMasked` boolean
      - `selfAdministered` true
      - `runner` object: Runner conditions as declared by the operator on the submission. Every other field in `conditions` is something the server observed; this block is not, so it is kept separate and flagged. A value the operator did not declare is null — undeclared, not defaulted to anything.
        - `selfDeclared` true, required: Always true. AIO did not observe these values and does not vouch for them.
        - `maxTokens` integer, nullable, required
        - `temperature` number, nullable, required
    - `referenceBand` ReferenceBand: Where the scores fall against the reference distribution for this pack (public/content/reference-distributions/{source}.json). Purely descriptive: it compares the attempt with a small panel of models measured under the same conditions in an arm that was never shown the pack. No band is a pass and no band is a failure. Part of the signed payload, and reproducible by anyone holding the same reference file.
      - `status` 'computed' | 'no-reference-data-yet', required: `no-reference-data-yet` when the pack has no reference distribution; no bands are then reported.
      - `source` string
      - `measuredAt` string, date-time
      - `models` integer: Size of the reference panel.
      - `methodologyVersion` string: Bands are comparable only within one methodology version.
      - `gateA` GateReferenceBand
        - `band` 'below-unadapted-range' | 'within-unadapted-range' | 'above-unadapted-range', required: Position relative to the observed minimum and maximum of the unadapted reference arm.
        - `unadaptedMin` number, required
        - `unadaptedMax` number, required
        - `unadaptedMean` number, required
      - `gateB` GateReferenceBand
        - `band` 'below-unadapted-range' | 'within-unadapted-range' | 'above-unadapted-range', required: Position relative to the observed minimum and maximum of the unadapted reference arm.
        - `unadaptedMin` number, required
        - `unadaptedMax` number, required
        - `unadaptedMean` number, required
    - `margin` ScoreMargin: How large a difference has to be before it is a difference. Computed deterministically from the pack's entry in the reference distribution file at issuance and part of the signed payload, so it cannot be restated afterwards and anyone holding the same file can reproduce it. Two scores that differ by less than the margin are not meaningfully different — this applies to comparing two reports as much as to comparing one report with a reference range.
      - `gateA` number, required: The model-nondeterminism floor: how far a Gate A score moves when one configuration is simply run again with nothing changed. Gate A draws no items, so this is the whole of its margin. Pack-independent.
      - `gateB` number, nullable, required: The draw-noise standard error predicted for this pack's Gate B pool (`drawNoise.predictedSE` in the reference file). Gate B carries this on top of nondeterminism because every attempt is scored on a fresh draw. null when the pack has no reference distribution to predict it from — `note` then says so.
      - `empiricalUpperBound` number, required: The largest run-to-run movement observed anywhere in the reference campaign, across gates and packs. A conservative bound: two scores that have not opened up by this much can be explained by noise on any combination.
      - `note` string, required: What each figure is, and that all of them are provisional — they rest on a handful of repeat pairs rather than large-N repeats.
    - `gateNote` string: Present only on packs whose reference entry carries both arms, where the effect of showing a model the pack clears the model-nondeterminism floor on Gate A but stays inside the pack's predicted Gate B draw noise. On such a pack, adaptation shows up on Gate A alone, and the note says so. It describes the reference panel rather than this measurement and states no verdict. Optional signed field, computed deterministically from the reference file at issuance.
    - `methodologyVersion` 'v0-draft' | 'v1-draft' | 'v2-draft', required: `v2-draft` = dual gate with V-weighted layer scoring (V 2 / E 1 / S 1), Gate B provision labels withheld at serving, and Gate B items served under opaque per-attempt handles. `v1-draft` = dual gate with equal layer weights (the legacy certificates). `v0-draft` = the single-gate certificates issued before the dual gate. The stamp records the methodology a record was issued under; existing records keep theirs and are never rescored or restamped, so their signatures keep verifying.
    - `issuedAt` string, date-time, required
    - `expiresAt` string, date-time, required: Six months after issuance. On a legacy certificate this was the validity period. On a score report it is how long AIO treats the measurement as current — past it the report is not withdrawn, it is simply old, and the badge says so.
    - `status` 'valid' | 'revoked', required
    - `signature` string, nullable: base64url Ed25519 signature over the canonical payload. null when the deployment has no signing key (development).
    - `signatureAlg` string, nullable
    - `signatureKeyId` string, nullable: Selects the key in /.well-known/aio-cert-key.json.
    - `itemCount` integer
    - `answeredCount` integer
  - `about` string
  - `legacy` boolean: Present and true on legacy certificates.
  - `valid` boolean
  - `effectiveStatus` 'valid' | 'expired' | 'revoked' | 'invalid-signature'
  - `expired` boolean
  - `verification` object
    - `signatureValid` boolean, nullable: null when the record carries no signature.
    - `note` string
    - `algorithm` 'Ed25519'
    - `keyId` string, nullable
    - `canonicalPayload` string: The exact UTF-8 message that was signed.
    - `publicKeyUrl` string, uri
    - `publicKey` object, nullable
    - `instructions` string[]
  - `badgeUrl` string, uri

## Other responses

- `400`: Malformed record id.
- `404`: No record with that id — it was not issued by AIO.
- `503`: Registry lookup is unavailable on this deployment.

---

[API](https://skmtc.dev/aioq/apis/aio-public-api.md) · [All operations](https://skmtc.dev/aioq/apis/aio-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/aioq/apis/aio-public-api/revisions/377b76120162?raw)
