Is AffixIO down right now?
The component list above answers it for your network. For an answer without loading a page, request api.affix-io.com/api/health and read the status field. It returns ok when the verification plane is serving.
Service status
Every check on this page runs in your browser, against the same public endpoints your own monitoring can call. There is no cached verdict written into this document, so what you read is the live path between you and the service, measured a moment ago rather than reported by us.
Each row names the endpoint it was checked against, so you can repeat the check yourself and get the same answer. Components are grouped by what breaks if they fail.
The route your SDK calls to verify a proof and get an eligibility outcome back. If this is unavailable, remote verification stops and your gate falls back to whatever you configured it to do.
GET https://api.affix-io.com/api/health, expect 200 and status ok
The circuit catalogue the engine has loaded. A drop in the circuit count means a family is missing and calls naming it will fail even though the API itself answers.
Read from the API health document: engine, circuit_count
The signing service behind post-quantum attestation on verification outcomes. Verification can still return a decision while this is degraded, but that decision arrives without signed evidence attached.
GET https://api.affix-io.com/v1/attestation/public-key, expect 200 and ML-DSA-65
The well-known document a verifier fetches to resolve the current public key. Attestations already in your possession keep verifying against a key you have cached, so this affects first-time resolution rather than existing evidence.
GET https://api.affix-io.com/.well-known/affix-mldsa65.json, expect 200
The append-only digest tree behind audit proofs and evidence export. The leaf count only ever moves up. If it moves down, treat the reading as wrong and tell us before you trust it.
Read from the API health document: merkle_root, merkle_leaf_count
Sign-in, API key management, usage figures and webhook endpoint registration. Keys already issued keep working while the Hub is unavailable, because verification does not route through it.
GET https://hub.affix-io.com/, expect 200
Public documentation, SDK reference and the machine-readable briefs. No runtime dependency, so a failure here is a documentation outage rather than a service one.
GET https://www.affix-io.com/robots.txt, expect 200
Where @affix-io/sdk and @affix-io/sdk-light are published. Operated by npm, not by us, and listed here because a registry problem blocks your installs and CI while every AffixIO service is fine.
GET https://registry.npmjs.org/@affix-io/sdk/latest, expect 200
Read straight out of the health document on the last successful check. These are the numbers worth screenshotting into a ticket, because they pin down which build answered you.
These values cannot be shown in this browser. The connection to api.affix-io.com succeeded, so the service answered, but this page's origin is not on the API's cross-origin read allow-list. The browser is therefore permitted to make the request and not to read what came back. The components above still report reachability because that much is established by the connection itself.
The figures are public. Read them straight from the endpoint:
curl -fsS https://api.affix-io.com/api/health | jq '{
policy_version, circuit_count, merkle_leaf_count,
attestation: .attestation.key_id
}'
Open the health document if you would rather read it in a tab.
Values appear once a check reads the response body.
Worth reading once, so you know how far to trust a green row.
The checks run from the browser you are reading this in. That is deliberate: a status page maintained by the same estate it reports on will happily tell you everything is fine while a region is dark. Measuring from the client puts your DNS resolver, your network and your TLS path inside the test, which is usually where the problem is when the service itself is healthy.
The cost is that a red row does not automatically mean an outage. A corporate proxy, a blocked request or a dead connection on your side produces the same result as a service that is down. Before escalating, run the same check from a second network. If one passes and the other fails, the fault is on the path rather than at our end.
Where the endpoint grants cross-origin read permission to this page, the check reads the response and asserts on real fields: status equal to ok, algorithm equal to ML-DSA-65, and so on. Where it does not, the check falls back to an opaque request that proves the host answered and times the round trip without seeing the body. Each row states which of the two it got, so a thin row is a permissions boundary and not a hidden failure.
Be clear about the limit of the second one. An opaque request cannot tell a 200 from a 403, because the browser hands back an empty response either way. A row marked reachable therefore means the host answered, not that it answered correctly. If a call of your own is failing while every row here reads reachable, run the commands below from a terminal: those see the status code and will show you what the browser was not allowed to.
Timings include DNS, TLS and your own network, and they are taken from a single request rather than a percentile over a window. Treat them as a smoke test. Use the X-RateLimit-* and x-request-id response headers on your own calls when you need to reason about real API behaviour under load.
It is static HTML with no server-side logic, deliberately the simplest thing on the estate so it survives a failure of the services it reports on. Do not have your alerting parse it. Point alerts at https://api.affix-io.com/api/health and keep this page for people.
Fixed definitions, so the same words mean the same thing in an incident as they do on a quiet day.
| State | Definition | What you should do |
|---|---|---|
| Operational | The check completed and the response matched what the component is supposed to return. | Nothing. |
| Degraded | The host answered, but the round trip was slower than the threshold for that component or the payload did not assert cleanly. | Expect slower verification. Check your own timeouts have headroom before you retry aggressively. |
| Unreachable | The request did not complete from this browser: DNS, TLS, connection or timeout. | Repeat from another network. If both fail, treat it as an outage and apply your fallback. |
| Not checked | The check has not run, or it was blocked before it reached the network. | Reload. If it stays unchecked, something local is blocking the request. |
| Maintenance | Planned work announced on this page in advance. | Follow the note on the entry. Windows are chosen to avoid changing verification behaviour. |
Written by hand, kept short, and served as JSON at /history/incidents.json so it can be pulled into your own change calendar.
No incidents recorded. This log opened on and holds nothing from before that date.
There is no uptime percentage on this page for the same reason. A figure like that only means something with a continuous measurement record behind it, and inventing one to fill the space would make every other number here worth less. Historic availability goes up once there is a full recorded period to publish.
No API key needed for any of them. If you are putting AffixIO on a gate that matters, your own monitoring should not depend on our status page being up.
Fails loudly on a non-2xx, a timeout, or a health document that does not say ok.
curl -fsS -m 10 https://api.affix-io.com/api/health \
| jq -e '.status == "ok"' > /dev/null
Public, uncached, and the fastest way to identify which build answered.
curl -fsS https://api.affix-io.com/api/health | jq '{
status, service, engine,
policy_version, circuit_count,
merkle_root, merkle_leaf_count
}'
Assert on the algorithm as well as the status code. A 200 carrying the wrong algorithm is not a pass.
curl -fsS -m 10 https://api.affix-io.com/v1/attestation/public-key \
| jq -e '.algorithm == "ML-DSA-65" and (.key_id | length) > 0'
A keyed route should refuse an unauthenticated request, so this returns 401 and a 200 would be the finding worth paging someone for. Run it when you want to confirm the auth layer, then stop.
test "$(curl -s -o /dev/null -w '%{http_code}' -m 10 \
https://api.affix-io.com/v1/health)" = "401"
Do not put that one in a monitoring loop. Unauthenticated requests to keyed routes are counted as authentication failures, and enough of them will get your address temporarily blocked from the whole API. A recurring check built on it eventually causes the outage it was meant to detect, and on a shared office address it takes your colleagues with it. Recurring checks belong on the unauthenticated routes above.
The registry this page renders from is published as JSON, with the probe URL and expected response for each component. Read it rather than hard-coding a list that drifts.
curl -fsS https://status.affix-io.com/components.json \
| jq -r '.groups[].components[] | "\(.id)\t\(.probe)"'
Mostly asked during an incident, which is the wrong time to be reading them for the first time.
The component list above answers it for your network. For an answer without loading a page, request api.affix-io.com/api/health and read the status field. It returns ok when the verification plane is serving.
The browser was allowed to open the connection but not to read the response. The API sends cross-origin read permission only to origins on its allow-list, so when this page is not on that list the check falls back to an opaque request. It still proves the host answered and still times the round trip. Nothing is wrong with the service.
A 403 carrying error: forbidden means your address has been temporarily blocked, not that the service is down. It is applied after repeated unauthenticated requests to routes that need an API key, so the usual causes are a client that lost its key, a monitoring loop pointed at a keyed route, or a colleague on the same office address doing one of those. It clears by itself after a short period, and requests carrying a valid key are unaffected.
A percentage needs a continuous measurement record behind it, and the log here opened on 15 August 2026. Publishing a number covering a period nobody measured would be made up, and it would undermine the readings that are real.
No. Proving runs locally against your own records with @affix-io/sdk or @affix-io/sdk-light. Remote verification, ML-DSA-65 attestation and Merkle anchoring are the parts that need this API. Whether an unavailable verify call fails open or fails closed is a decision that belongs in your application.
Yes. An ML-DSA-65 signature is verified against the public key, and if you have cached that key the check is entirely local. Key discovery being unavailable affects resolving a key you do not hold yet, not evidence you already have.
Posted here before it starts and kept in the log afterwards, in the page and in incidents.json. Windows are picked so that verification behaviour does not change under you mid-window.
Email hello@affix-io.com with the x-request-id from a failing response, the endpoint, the UTC timestamp and the status code you got. That header is on every response and it is what makes the report traceable.