# Capture points API

> The public endpoint that turns a submission from another platform into contact + consent. Exact contract, fields, responses, the August 2026 change and which contact level each submission creates.

Fuente / source: https://soporte.konverda.com/en/docs/developers/capture-points
Idioma / language: en
Actualizado / updated: 2026-08-26

---
A **capture point** exposes a public **platform-to-platform** endpoint (Zapier, Make, your backend) that turns a submission into contact + consent, with its source recorded and, if you wire one up, a welcome automation.

Points are created and managed in the app, under **«Captación → API»** (capture → API). Each point's exact URL is on its own row.

:::nota
To capture **people** with a page, this endpoint is not the way: use **«Captación → Formularios»** (capture → forms), which hosts the page, its consent checkbox and its analytics. This endpoint is for machines.
:::

## The endpoint {#endpoint}

```http
POST https://app.konverda.com/webhooks/capture/<token-del-punto>
Content-Type: application/json
```

`application/json` is recommended; `application/x-www-form-urlencoded` is also accepted. **The response is ALWAYS JSON.**

:::aviso
The URL contains the point's token: it is the credential. Treat it like a password. If it leaks, deactivate the point from **«Captación → API»** (capture → API) and create a new one.
:::

:::importante
**25 August 2026.** Until that date this endpoint accepted submissions without the `consent` field, and also served browser forms (*urlencoded* posts answered with HTML pages). Both things changed on the same day and were not announced.

A submission without affirmative `consent` answers `422 consent_required` and **registers nobody**.


## Minimum payload {#payload}

```json
{
  "phone": "+34 612 345 678",
  "name": "Ana Pérez",
  "consent": true
}
```

## Field reference {#fields}

| Field | Type | Description |
|---|---|---|
| `phone` | text · recommended | The contact's WhatsApp phone number. Local format is allowed if the server has a default country prefix. If your form has it as optional and the person leaves it empty, send the registration anyway: it is accepted with `200`, creates no contact and counts as «sin teléfono» in the point's analytics (the WhatsApp rate needs that figure). A present but unrecognisable value is rejected. |
| `name` | text · optional | The contact's name. |
| `email` | text · optional | Stored on the contact's record (the most recent one wins). It is not used for messaging; a value in an unrecognisable format is ignored without rejecting the submission. |
| `consent` | required when `phone` is present · `true`, `1`, `"1"`, `"true"`, `"yes"`, `"on"`, `"sí"` or `"si"` | States that the person agreed to receive WhatsApp messages ON YOUR PLATFORM. With a phone and without this signal the submission is rejected with `422 consent_required` and no contact is created; without a phone there is nothing to consent to yet, so it is not required. Which LEVEL it grants is decided by the point's configuration — see [Consent](#consent). |
| `_hp` | text · leave EMPTY | Invisible anti-bot trap: any value marks the submission as a bot (and answers `200` on purpose, creating nothing). |
| `cf-turnstile-response` | text | Cloudflare Turnstile token — only if the point requires it. |

:::nota
This endpoint accepts the string forms on purpose: what reaches it is forms and automation tools that can only send strings. The [orders API](/en/docs/developers/orders-api#fields) is stricter — there `consent` has to be a real boolean. It is not an inconsistency: they are two different senders.
:::

## Trying it with curl {#curl}

```bash
curl -X POST 'https://app.konverda.com/webhooks/capture/<token-del-punto>' \
  -H 'Content-Type: application/json' \
  -d '{ "phone": "+34612345678", "name": "Ana Pérez", "consent": true }'
```

## Responses {#responses}

| Code | Body | Meaning |
|---|---|---|
| `200` | `{"ok":true}` | Recorded — or received without a phone (counted, no contact created) — or a bot silently filtered out (`_hp` filled in). A bot gets the same `200` on purpose: a rejection would teach it which field gave it away. |
| `400` | `{"error":"bad_payload","message":"…"}` | The body could not be read or is not an object with fields (invalid JSON, `text/plain`, an empty `{}`). |
| `403` | `{"error":"verification_failed"}` | Turnstile not verified (the point requires it and the token does not validate). |
| `404` | `{"error":"not_found"}` | Unknown token, or deactivated point. |
| `422` | `{"error":"consent_required","message":"…"}` | The payload does not state consent (`consent` absent or not affirmative). The `message` explains in one sentence what is missing. |
| `422` | `{"error":"invalid_phone"}` | `phone` present but unrecognisable. (Absent is NOT an error: see [fields](#fields).) |
| `429` | `{"error":"rate_limited"}` | More than 10 submissions per minute per IP and point. |

Every refusal (`400`, `403`, `422`) is counted in the point's analytics with its reason — «Rechazados en la puerta» — so a misconfigured integration shows in the funnel and not only in this error code.

## Consent: which contact level each submission creates {#consent}

A contact has TWO possible levels. **«Marketing»** = they can receive campaigns, waves, proactive automations and 1:1 templates. **«No»** = we can only reply to them when they write, and no message started by us reaches them (the attempt is logged as `not_marketing`).

Here the level is not decided by your payload alone: it is decided by **the point's configuration** («Consentimiento explícito» — explicit consent, on the point's row) combined with the `consent` you send.

| Point configuration | Basis recorded | Resulting opt-in | What they can receive |
|---|---|---|---|
| «Consentimiento explícito» ON + affirmative `consent` | `checkbox` | «Marketing» | Everything: campaigns, waves, the welcome automation and 1:1 templates. Being an explicit act by the person themselves, it lifts a previous opt-out. |
| «Consentimiento explícito» OFF + affirmative `consent` | `form` | «No» | Only replies when the person writes. This point's welcome automation is NOT sent (it is logged as `not_marketing`). A previous opt-out is always respected. |
| `consent` absent or false, with `phone` | — (not processed) | No contact created | `422 consent_required`. |
| No `phone` | — | No contact created | `200`: the submission counts as «sin teléfono» in the point's analytics. |

:::aviso
`consent` is required and it is not a formality: send it affirmative only when the person really agreed (a checkbox on your platform, not a hardcoded value). And check the point's configuration: if its «Consentimiento explícito» is off, ALL the contacts entering through here will sit at level «No» — they appear in **«Contactos»** (contacts), but they will receive neither the welcome nor any campaign until they give their explicit consent by some other route.
:::

## A contact at level «No» is not a lost contact {#level-no}

The moment **they write to you**, the conversation opens and you can reply. That is where **keywords** come in: a word the person types is a door they open themselves, so it works at any consent level. If you capture leads through this endpoint, give them a word to write.

## Read next {#read-next}

- [The marketing opt-in and «Añadir a marketing»](/en/docs/contacts-and-consent/the-marketing-opt-in)
- [Opt-outs and what the platform remembers](/en/docs/contacts-and-consent/opt-outs-and-what-the-platform-remembers)
- [Orders API (generic connection)](/en/docs/developers/orders-api) — the other public endpoint, for sales.
