API reference

Chain heal

Scan the chain for breaks, gaps and signature failures, and append repair records. Repair is additive; nothing is edited or deleted.

POST /v1/heal/auto/start

Start the periodic scan

Starts a background scan of this account's chain every period_seconds inside the API process.

Auth
session cookie or API key
Capability
governance
Success
HTTP 200

The task lives in the API process and does not survive a restart. GET /v1/heal/status reports auto_running, which is how you notice it stopped.

Parameters

None.

Request body

period_seconds integer
Default 300.

Example request

curl

curl -sS -X POST "https://api.afaprotocol.com/v1/heal/auto/start" \
  -H "X-API-Key: afa-beta-EXAMPLE-e4qs" \
  -H "Content-Type: application/json" \
  -d '{
  "period_seconds": 300
}'

Python

import requests

API = "https://api.afaprotocol.com"
headers = {"X-API-Key": "afa-beta-EXAMPLE-e4qs"}
payload = {
    "period_seconds": 300
}

r = requests.post(f"{API}/v1/heal/auto/start", headers=headers, json=payload, timeout=30)
r.raise_for_status()
print(r.json())

Example response

HTTP 200
{
  "period_seconds": 300,
  "running": true,
  "started_at": "2026-09-01T14:32:00+00:00",
  "task_id": "heal-2f6e1a0c9b4d",
  "user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14"
}

Errors

StatusCodeMeaning
401missing_token / invalid_or_expired_api_keyNo credential, an expired session, or a revoked or expired key.
403scope_missingA key limited by scopes lacks governance; the body names it.
422validation errorA required field is missing or a value has the wrong type.

What would show this is false

Stop it and read status: auto_running false. A service restart also clears it, and status shows that too.

POST /v1/heal/auto/stop

Stop the periodic scan

Stops the background scan for this account.

Auth
session cookie or API key
Capability
governance
Success
HTTP 200

Parameters

None.

Request body

None.

Example request

curl

curl -sS -X POST "https://api.afaprotocol.com/v1/heal/auto/stop" \
  -H "X-API-Key: afa-beta-EXAMPLE-e4qs"

Python

import requests

API = "https://api.afaprotocol.com"
headers = {"X-API-Key": "afa-beta-EXAMPLE-e4qs"}

r = requests.post(f"{API}/v1/heal/auto/stop", headers=headers, timeout=30)
r.raise_for_status()
print(r.json())

Example response

HTTP 200
{
  "running": false,
  "started_at": "2026-09-01T14:32:00+00:00",
  "stopped": true,
  "stopped_at": "2026-09-01T15:02:00+00:00",
  "task_id": "heal-2f6e1a0c9b4d",
  "user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14"
}

Errors

StatusCodeMeaning
401missing_token / invalid_or_expired_api_keyNo credential, an expired session, or a revoked or expired key.
403scope_missingA key limited by scopes lacks governance; the body names it.

What would show this is false

Stop when nothing runs: stopped false, not an error. The response distinguishes the two cases.

POST /v1/heal/run

Append repair records

Appends one chain_repair event per finding at the tip of the chain, or only counts them when dry_run is true.

Auth
session cookie or API key
Capability
governance
Success
HTTP 200

Repair is additive: no original event is modified or deleted. The repair record carries the diagnostic, so the break stays visible in the history.

Parameters

None.

Request body

dry_run boolean
Default true.
machine_id string or null
No description in the schema.

Example request

curl

curl -sS -X POST "https://api.afaprotocol.com/v1/heal/run" \
  -H "X-API-Key: afa-beta-EXAMPLE-e4qs" \
  -H "Content-Type: application/json" \
  -d '{
  "dry_run": true,
  "machine_id": "worker-1"
}'

Python

import requests

API = "https://api.afaprotocol.com"
headers = {"X-API-Key": "afa-beta-EXAMPLE-e4qs"}
payload = {
    "dry_run": True,
    "machine_id": "worker-1"
}

r = requests.post(f"{API}/v1/heal/run", headers=headers, json=payload, timeout=30)
r.raise_for_status()
print(r.json())

Example response

HTTP 200
{
  "actions": [],
  "breaks": 0,
  "completed_at": "2026-09-01T14:31:00+00:00",
  "dry_run": true,
  "gaps": 0,
  "machine_id": "worker-1",
  "merkle_root_status": "ok",
  "signature_failures": 0,
  "skipped": 0,
  "user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14",
  "would_write": 0,
  "written": 0
}

Errors

StatusCodeMeaning
401missing_token / invalid_or_expired_api_keyNo credential, an expired session, or a revoked or expired key.
403scope_missingA key limited by scopes lacks governance; the body names it.
422validation errorA required field is missing or a value has the wrong type.

What would show this is false

With dry_run true, written is 0 and a following scan reports the same total_events.

POST /v1/heal/scan

Scan the chain

Walks the account's events and reports breaks, gaps and signature failures without changing anything.

Auth
session cookie or API key
Capability
governance
Success
HTTP 200

A break is a prev_hash that does not match the previous event's payload_hash. A gap is a missing sequence number. A signature failure is a signed event that does not verify against the machine's registered key.

Parameters

None.

Request body

machine_id string or null
No description in the schema.

Example request

curl

curl -sS -X POST "https://api.afaprotocol.com/v1/heal/scan" \
  -H "X-API-Key: afa-beta-EXAMPLE-e4qs" \
  -H "Content-Type: application/json" \
  -d '{
  "machine_id": "worker-1"
}'

Python

import requests

API = "https://api.afaprotocol.com"
headers = {"X-API-Key": "afa-beta-EXAMPLE-e4qs"}
payload = {
    "machine_id": "worker-1"
}

r = requests.post(f"{API}/v1/heal/scan", headers=headers, json=payload, timeout=30)
r.raise_for_status()
print(r.json())

Example response

HTTP 200
{
  "breaks": [],
  "clean": true,
  "gaps": [],
  "machine_id": "worker-1",
  "merkle_root_status": "ok",
  "scanned_at": "2026-09-01T14:30:00+00:00",
  "signature_failures": [],
  "total_events": 6,
  "user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14",
  "verified": 6
}

Errors

StatusCodeMeaning
401missing_token / invalid_or_expired_api_keyNo credential, an expired session, or a revoked or expired key.
403scope_missingA key limited by scopes lacks governance; the body names it.
422validation errorA required field is missing or a value has the wrong type.

What would show this is false

clean is true only when all three lists are empty and merkle_root_status is ok. A root that cannot be verified reads mismatch, never a clean true.

GET /v1/heal/status

Last scan and repair

Returns the cached results of the last scan and repair for this account, and whether the periodic scan is running.

Auth
session cookie or API key
Capability
governance
Success
HTTP 200

Parameters

None.

Request body

None.

Example request

curl

curl -sS -X GET "https://api.afaprotocol.com/v1/heal/status" \
  -H "X-API-Key: afa-beta-EXAMPLE-e4qs"

Python

import requests

API = "https://api.afaprotocol.com"
headers = {"X-API-Key": "afa-beta-EXAMPLE-e4qs"}

r = requests.get(f"{API}/v1/heal/status", headers=headers, timeout=30)
r.raise_for_status()
print(r.json())

Example response

HTTP 200
{
  "auto_running": false,
  "last_repair": null,
  "last_scan": {
    "breaks": [],
    "clean": true,
    "gaps": [],
    "machine_id": "worker-1",
    "merkle_root_status": "ok",
    "scanned_at": "2026-09-01T14:30:00+00:00",
    "signature_failures": [],
    "total_events": 6,
    "user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14",
    "verified": 6
  }
}

Errors

StatusCodeMeaning
401missing_token / invalid_or_expired_api_keyNo credential, an expired session, or a revoked or expired key.
403scope_missingA key limited by scopes lacks governance; the body names it.

What would show this is false

Before any scan the response reads last_scan null. The cache is per account and per process; a restart clears it.