POST /api/v1/agent/heartbeat
Submit a paid heartbeat. Replaces the deprecated checkin endpoint with economic accountability.
Auth: Authorization: Bearer pvn_...
Base URL: https://provenonce.io
Requires an active SIGIL for root agents (depth 0). Child agents (depth > 0) can heartbeat without a SIGIL — they inherit provenance from their parent. Root agents without a SIGIL receive HTTP 403.
Request
curl -X POST https://provenonce.io/api/v1/agent/heartbeat \
-H "Content-Type: application/json" \
-H "Authorization: Bearer pvn_..." \
-d '{
"payment_tx": "5xYzAbCd...",
"global_anchor": 4215
}'Request body
| Field | Type | Required | Description |
|---|---|---|---|
payment_tx | string | Yes | Solana transaction signature for the heartbeat fee |
global_anchor | number | No | Global anchor index claim. Server validates and uses the true server-side value. |
Response
{
"ok": true,
"agent_hash": "0xfd752396...",
"passport": {
"format_version": 1,
"agent_hash": "0xfd752396...",
"agent_public_key": "...",
"authority_key_id": "pvn-ed25519-3f5b2f8a1b7c9d10",
"identity_class": "autonomous",
"registered_at_beat": 100,
"sigil_issued_at_beat": 200,
"last_heartbeat_beat": 5663,
"lineage_chain_hash": "0xdef456...",
"issued_at": 1771310460000,
"valid_until": 1771396860000,
"provenonce_signature": "a1b2c3d4e5f6..."
},
"lineage_proof": { "...same as passport..." },
"total_heartbeats": 142,
"heartbeat_count_epoch": 142,
"billing_epoch": 1,
"current_beat": 5663,
"fee": {
"amount_sol": 0.0005,
"amount_lamports": 500000,
"tier": 1,
"payment_tx": "5xYzAbCd..."
}
}| Field | Type | Description |
|---|---|---|
ok | boolean | true on success |
agent_hash | string | Agent identity hash |
passport | object | Fresh Ed25519-signed Passport (see below) |
lineage_proof | object | Deprecated alias for passport (identical object, sunset 2026-09-01) |
total_heartbeats | number | Updated total heartbeat count after this heartbeat |
heartbeat_count_epoch | number | Heartbeat count within current billing epoch |
billing_epoch | number | Current billing epoch number |
current_beat | number | Current beat index |
fee | object | Fee details for this heartbeat |
Passport
Each heartbeat returns a fresh Ed25519-signed Passport, valid for 24 hours. See authority key for offline verification.
| Field | Type | Description |
|---|---|---|
format_version | number | Always 1 — canonical field order for verification |
agent_hash | string | Agent identity hash |
agent_public_key | string | null | Agent wallet key/address used in proof binding |
authority_key_id | string | Authority key identifier used for signing |
identity_class | string | narrow_task, autonomous, or orchestrator |
registered_at_beat | number | Beat at registration |
sigil_issued_at_beat | number | null | Beat when SIGIL was issued |
last_heartbeat_beat | number | Last attested heartbeat beat |
lineage_chain_hash | string | Hash of lineage event chain |
issued_at | number | Unix timestamp (ms) |
valid_until | number | Unix timestamp (ms) expiry |
provenonce_signature | string | Hex Ed25519 signature over canonical JSON |
Volume-tiered fees
Heartbeat fees decrease with volume within a billing epoch (100,000 beats).
| Heartbeats in epoch | Fee per heartbeat (SOL) | Tier (numeric) |
|---|---|---|
| 1-100 | 0.0005 | 1 |
| 101-1,000 | 0.0003 | 2 |
| 1,001+ | 0.0002 | 3 |
The fee field in the response reflects the tier applied to this heartbeat.
Heartbeat caps per epoch
Each identity class has a maximum number of heartbeats per billing epoch.
| Identity class | Cap per epoch |
|---|---|
narrow_task | 1,000 |
autonomous | 5,000 |
orchestrator | 20,000 |
Once the cap is reached, further heartbeats return HTTP 429 until the next epoch.
Minimum interval
Heartbeats must be at least 10 beats apart (configurable server-side). Submitting a heartbeat before the minimum interval returns HTTP 429.
{
"error": "Heartbeat too soon",
"code": "HEARTBEAT_TOO_SOON",
"next_eligible_beat": 5670
}Fee split
All heartbeat fees are allocated as follows:
| Allocation | Percentage |
|---|---|
| Operations | 30% |
| Contributors | 30% |
| Development | Starts at 15%, decays 1%/year to 5% floor |
| Treasury | Starts at 15%, absorbs development decay |
| Referral | 10% |
Development starts at 15% and decays by 1% per year to a 5% floor. Treasury absorbs the released share.
Error responses
| Status | Body | Cause |
|---|---|---|
| 400 | {"error": "...", "code": "PAYMENT_REQUIRED"} | Missing payment_tx |
| 400 | {"error": "...", "code": "PAYMENT_INVALID"} | Transaction not found or amount mismatch |
| 400 | {"error": "...", "code": "PAYMENT_SENDER_MISMATCH"} | Payment sender doesn’t match agent wallet |
| 401 | {"error": "...", "code": "AUTH_MISSING"} | Missing or invalid API key |
| 403 | {"error": "...", "code": "WALLET_REQUIRED"} | Agent is still api-sponsored; link wallet first |
| 403 | {"error": "...", "code": "SIGIL_REQUIRED"} | Root agent has no SIGIL (descendants bypass) |
| 403 | {"error": "...", "code": "SPONSOR_PARENT_FROZEN"} | Sponsor parent is frozen |
| 409 | {"error": "...", "code": "PAYMENT_ALREADY_USED"} | Payment tx already used for another heartbeat |
| 429 | {"error": "...", "code": "HEARTBEAT_TOO_SOON"} | Below minimum 10-beat interval |
| 429 | {"error": "...", "code": "VOLUME_CAP_REACHED"} | Heartbeat cap exceeded for identity class |
| 429 | {"error": "...", "code": "SPONSOR_CAP_REACHED"} | Sponsorship epoch cap exhausted |
| 429 | {"error": "...", "code": "RATE_LIMITED"} | Endpoint rate limit exceeded |
Rate limit: 60/min per endpoint subject
For authenticated routes, buckets are keyed by endpoint path + authenticated agent identity. If identity is missing, the server falls back to endpoint path + client IP.