---
title: curl
description: Pure curl recipes for ad-hoc heartbeats, smoke tests, and CI hooks.
section: integrations
order: 2
---

# curl

The lowest-common-denominator way to fire a heartbeat: one HTTP call, one finished run. For the full endpoint reference, see [GET /v1/ping](/docs/api/ping) and [POST /v1/heartbeats](/docs/api/heartbeats).

## The minimal heartbeat

```bash
curl 'https://eu.ingest.agentping.io/v1/ping?key=ping_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b6&agent=daily-summary&status=ok'
```

Response is `OK\n`. The run lands in your dashboard within a second.

## Adding cost and duration

```bash
curl 'https://eu.ingest.agentping.io/v1/ping?key=ping_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b6&agent=daily-summary&status=ok&cost_usd=0.084&duration_ms=12300'
```

`cost_usd` is trusted as supplied on heartbeats; there are no `llm_call` events for the server to derive it from.

## POST when query strings aren't enough

For structured metadata, explicit timestamps, or anything beyond the 256-char `metadata` field that `GET` supports:

```bash
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": "nightly-rollup",
    "status": "ok",
    "started_at": "2026-05-15T03:00:00.000Z",
    "finished_at": "2026-05-15T03:04:17.300Z",
    "cost_usd": 0.142,
    "metadata": {"customers_processed": 4821, "shard": "eu-west"}
  }'
```

`id` is optional. Supply one for idempotent retries (same `id`, matching fields = 200 no-op). Omit it and the server mints one.

## Authentication

Three transports, all equivalent:

| Method | Example |
|--------|---------|
| Header | `Authorization: Bearer apk_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b6` |
| Header alias | `X-AgentPing-Key: ping_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b6` |
| Query string | `?key=ping_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b6` (only on `GET /v1/ping`) |

Ping tokens in URLs, API keys in headers. See [Authentication](/docs/api/auth).

## Error handling

```bash
curl --fail-with-body 'https://eu.ingest.agentping.io/v1/ping?key=ping_eu_018f3a2b9c1d7e8fa4b9c2d7e8f1a3b6&agent=competitor-scan&status=ok'
```

`--fail-with-body` returns a non-zero exit code on 4xx/5xx and still prints the body:

```
HTTP/1.1 401 Unauthorized
Content-Type: text/plain

This ping token is scoped to agent "daily-summary".
You attempted to fire a heartbeat for "competitor-scan".
```

Two agent slugs side by side, misconfiguration named in the body.

:::tip
A one-liner smoke test for every deploy:
`curl --fail-with-body 'https://eu.ingest.agentping.io/v1/ping?key=ping_eu_...&agent=post-deploy&status=ok'`. Fail the pipeline on non-zero exit; you'll know within seconds when credentials drift or an agent is renamed.
:::
