Heartbeats

A heartbeat is a single-call run: started and finished in one request, no separate events. Lands in the same dashboard as full SDK runs; upgrading later doesn't migrate data.

For shell one-liners, see GET /v1/ping. This page covers the JSON POST variant.

POST /v1/heartbeats

https://eu.ingest.agentping.io/v1/heartbeats

Request

Field Type Required Description
id string No Client-generated. Format run_<region>_<32 hex>. Omit to let the server mint one.
agent string Yes Slug. New agents are auto-created.
status string No ok, fail, start, timeout. Default ok. start opens a run without finishing it.
started_at string (ISO 8601, UTC) No Default: server receive time.
finished_at string (ISO 8601, UTC) No Default: server receive time.
cost_usd number No Total cost in US dollars. Overrides token pricing when both are sent.
model string No Model id (e.g. gpt-4o). With token counts and no cost_usd, the run is priced from your rate card.
provider string No Provider (openai, anthropic, ...). Pairs with model for pricing.
input_tokens integer No Prompt/input tokens. Priced against the rate card when model is set.
output_tokens integer No Completion/output tokens. Priced against the rate card when model is set.
cached_input_tokens integer No Cache-read tokens, billed at the cached rate.
duration_ms integer No If absent, computed from started_at/finished_at or from a prior start with the same id.
metadata object No Flat key/value JSON. Paid feature, limits below.

Response

202 Accepted on first write. 200 OK on idempotent retry. 409 Conflict if id exists with mismatching agent or started_at.

{
  "id": "run_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b9",
  "agent": "daily-summary",
  "status": "ok",
  "started_at": "2026-05-15T14:32:00.000Z",
  "finished_at": "2026-05-15T14:32:12.300Z",
  "received_at": "2026-05-15T14:32:12.450Z",
  "cost_usd": 0.084,
  "duration_ms": 12300
}

Example

curl -X POST https://eu.ingest.agentping.io/v1/heartbeats \
  -H "Authorization: Bearer ping_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b6" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "run_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b9",
    "agent": "daily-summary",
    "status": "ok",
    "started_at": "2026-05-15T14:32:00.000Z",
    "finished_at": "2026-05-15T14:32:12.300Z",
    "cost_usd": 0.084,
    "metadata": {"items_processed": 47}
  }'

Let AgentPing price it from tokens

When the caller has the model and token usage (an n8n AI node, a Make or Zapier step, a script that read the provider's usage block) send those instead of computing a cost:

curl -X POST https://eu.ingest.agentping.io/v1/heartbeats \
  -H "Authorization: Bearer ping_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b6" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "lead-enrichment",
    "status": "ok",
    "provider": "openai",
    "model": "gpt-4o",
    "input_tokens": 1240,
    "output_tokens": 380
  }'

AgentPing prices the run from your rate card. An unpriced model records at zero cost and shows in the unpriced-models banner on the Spend page.

Heartbeat vs full run

Aspect Full run Heartbeat
Number of HTTP calls 2 to N (start, events, finish) 1
Events recorded One row per event None
Cost computation Server-side from llm_call events Client cost_usd, or server-side from model + token counts
Per-step latency Yes, per event Run-level only
Best for Agent loops with multiple LLM or tool steps Webhooks, cron, n8n flows, single-action jobs

When to use heartbeats

Heartbeats fit when:

  • The job is a webhook (n8n, Zapier, Make, Vercel cron) and the SDK can't load.
  • The job is a shell script or Lambda with one LLM call wrapped in retries.
  • A team wants monitoring today; the SDK can be added later without losing history.

Full runs (POST /v1/runs + events + finish) fit when:

  • An agent makes more than one LLM call.
  • Tool calls or guardrail outcomes matter for debugging.
  • Per-step latency is interesting.
  • The SDK is already loaded.