# Verify a launch token

`POST /v1/lead-actions/verify`

Checks a lead-action token and returns the team member and lead it was issued for.

**Scope:** none, any valid key

**Access:** Any valid key may call it, but only the key the lead action belongs to can verify that action's tokens.

Verify from your server only: the key must never reach a browser. A token can be verified more than once until it expires, so anyone who obtains the full URL in those 10 minutes can use it; keep it out of logs and analytics.

With a `leads:read` key you can then read the lead with `GET /v1/leads/{lead_id}`, and with `pipeline:write` move its card for the member by sending `member.id` as `acting_member_id`.

Every failed check gets the same `404 invalid_token`: a malformed, altered or expired token, one issued for another key, a key that no longer has a lead action, a key or member (the key's own or the one who clicked) that can no longer reach the lead's campaign, a member who clicked but can no longer open the card or is no longer active, or a lead or card that no longer exists. Ask the team member to click the button again; retrying the same token will not help.

## Body

**Content type:** `application/json`

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `token` | `string` | Yes | The `dialecho_token` query parameter, exactly as received. |

## Response

**Status:** `200 OK`

| Name | Type | Description |
| --- | --- | --- |
| `member` | `object` | The team member who clicked the button. |
| `member.id` | `UUID` | Their DialEcho member id. |
| `member.name` | `string \| null` | Their profile name, or `null`. |
| `member.email` | `string \| null` | Their email, or `null`. |
| `lead_id` | `UUID` | The lead the button was clicked on. |
| `pipeline_lead_id` | `UUID` | The pipeline card the button was clicked on; it belongs to that lead. |
| `campaign_id` | `UUID` | The card's campaign. |
| `expires_at` | `timestamp` | When the token expires (ISO 8601, UTC). |

## Example request

**curl**

```bash
curl -X POST "https://development.agencydevworks.ai/v1/lead-actions/verify" \
  -H "Authorization: Bearer dei_your_key" \
  -H "Content-Type: application/json" \
  -d '{
  "token": "eyJ2IjoxLCJleGFtcGxlIjp0cnVlfQ.exampleSignature"
}'
```

**JavaScript**

```js
const response = await fetch("https://development.agencydevworks.ai/v1/lead-actions/verify", {
  method: "POST",
  headers: {
    "Authorization": "Bearer dei_your_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "token": "eyJ2IjoxLCJleGFtcGxlIjp0cnVlfQ.exampleSignature"
  }),
});
const data = await response.json();
```

## Example response

**Status:** `200 OK`

```json
{
  "member": {
    "id": "ffffffff-0000-4000-8000-000000000001",
    "name": "Jordan Rivera",
    "email": "jordan@example.com"
  },
  "lead_id": "aaaaaaaa-0000-4000-8000-000000000001",
  "pipeline_lead_id": "dddddddd-0000-4000-8000-000000000001",
  "campaign_id": "cccccccc-0000-4000-8000-000000000001",
  "expires_at": "2026-11-02T15:10:00Z"
}
```

## Errors

| HTTP | Code | When |
| --- | --- | --- |
| 404 | `invalid_token` | The token is not valid for this key, for any reason. Ask the member to click the button again. |
| 413 | `payload_too_large` | The body is larger than 1 MB. It was not read. |
| 422 | `invalid_request` | The body is not `{"token": "<string>"}`. |

Every endpoint can also answer `401 invalid_api_key`, `429 rate_limited` and `503 dependency_unavailable`. See [Errors](/api/#errors) in the overview.

## Related endpoints

- `GET /v1/leads/{lead_id}` · [Retrieve a lead](/api/leads/get)
- `PUT /v1/leads/{lead_id}/stage` · [Move a lead's card](/api/leads/move-stage)
