# Form forwarding (webhook)

> Receive every completed form in your own API

- Page: https://tbit.app/docs/api/forms-webhook
- Base URL: `https://rest-api.tbit.app/v1`
- Authentication: `X-API-Key` header with your key on every request (the examples read it from the `TBIT_API_KEY` environment variable)

## Overview

When a customer finishes a form in a conversation, TBit can call your API with the answers. There are two modes. Validate and forward (recommended when the form asks for documents): TBit checks the attached documents with vision, cross-checks them against what the person declared, tells the customer the result and, only if everything matches, POSTs the profile to your URL with retries. Direct call: TBit POSTs the raw form values to your URL as soon as the form is complete, with no validation and no retries.

## How to configure it

Any of these three doors writes the same setting on the form (its closing action):

- Canvas (newui.tbit.app): Forms → open the form row → “Forward when finished…”. A pre-filled form asks for the mode, the destination URL, an optional bearer token and the payload profile.
- MCP (Claude, ChatGPT…): manage_form with action=set_forward, form_id from list_forms, mode, url, token and profile. The change is proposed and you confirm it.
- Platform app: Forms → edit → closing action → API. This is the low-level view: the URL of the document validator, a bearer with TBit’s secret and the X-Tbit-Forward-* headers.

## Example: configure from the MCP

```json
manage_form
{
  "action": "set_forward",
  "form_id": "6917da72ed0bc91ea5532858",
  "mode": "validate_forward",
  "url": "https://api.tunegocio.com/tbit/perfiles",
  "token": "<tu bearer>",
  "profile": "generic"
}
```

## Mode 1 · Validate documents and forward

### Flow

1. The customer completes the form (with file fields for the documents). 2. TBit reads each document, extracts name and document number and cross-checks them with the declared values. 3. The customer gets a message: everything matches, a mismatch (and what to resend) or an unreadable file. 4. If the verdict is MATCH, TBit POSTs to your URL.

### Headers we send

|  |
|  |
| `Content-Type` | application/json |
| `Authorization` | Bearer <the token you configured> (only if there is one) |
| `X-Bot-Provider` | tbit |
| `X-Event-Type` | profile.completed |
| `X-Tbit-Form-Data-Id` | <id of the submission, for deduplication> |

### Payload (profile: generic)

fields carries every answered field by its name in the form; document_validation carries the verdict per document. If TBit built a custom profile for your company, the body follows that data contract instead and the profile name is the one you were given.

### Retries and idempotency

Answer 2xx as fast as you can (10 s timeout). On 500, 502, 503, 504 or a network error TBit retries after 30 s, 2 min, 10 min and 1 h. Other statuses are not retried. Retries are kept in memory: if the engine restarts in between they are lost, so design your endpoint as at-least-once and dedupe by formDataId (also in the X-Tbit-Form-Data-Id header).

```json
{
  "formDataId": "6aabbe45706082120e74fc75",
  "agentId": "6aaab0521c2b87a579ccc624",
  "activityId": "6aabbe3c58181a93243f7298",
  "fields": {
    "Nombre completo": "Ana Pérez",
    "Cédula": "1032456789",
    "Gasto en alimentación": 900,
    "Foto del DNI": { "kind": "file", "url": "https://api.tbit.app/media/…/dni.jpeg" }
  },
  "document_validation": {
    "verdict": "MATCH",
    "results": [
      { "field": "Foto del DNI", "document_kind": "dni", "verdict": "MATCH",
        "checks": { "full_name": true, "document_number": true } }
    ]
  }
}
```

## Mode 2 · Direct call

As soon as the form is complete, TBit POSTs a JSON with one key per form field (its name in the form) plus formId, agentId and formDataId. Authentication follows what you configured: Bearer (Authorization: Bearer …), Basic (Authorization: Basic …) or an API key (X-API-Key header), plus any extra headers. There are no retries: a failed call stays failed.

```json
{
  "Nombre completo": "Ana Pérez",
  "Cédula": "1032456789",
  "Gasto en alimentación": 900,
  "formId": "6917da72ed0bc91ea5532858",
  "agentId": "6aaab0521c2b87a579ccc624",
  "formDataId": "6aabbe45706082120e74fc75"
}
```

## Verifying calls

Every call is recorded with its request, response, HTTP status and attempts. The TBit team sees them in the Developer panel of the canvas and can review them with you; for your own logs, log formDataId on your side.
