> ## Documentation Index
> Fetch the complete documentation index at: https://docs.3i.life/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing & Error Handling

> Pre-flight validation using Listen Mode, idempotency retries, and machine-readable error catalog.

## Pre-Flight Testing (Listen Mode)

Before sending live production traffic, partners can verify their payload syntax, parameter mapping, and appointment scheduling formats **safely without creating live records**.

<Info>
  **Zero Database Contamination:** When `"listen": true` is included in your JSON payload, 3i CRM:

  * **Does NOT** create a lead in the agent's pipeline or dial queue.
  * **Does NOT** book an appointment on the agent's live calendar.
  * **Does NOT** trigger automated SMS or phone calls to the prospect.
  * **Does NOT** trigger external partner sync or analytics webhooks.
  * Captures the sample payload in the agent's **Lead Sources → Recent Payloads** workbench so the receiving agent can visually verify and map custom fields with one click.
</Info>

***

## Test Scenario 1: Standard Inbound Lead Test

Test your authentication, contact fields, and custom metadata without creating a workable contact:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.3i.life/functions/v1/inbound-lead-gateway" \
    -H "Content-Type: application/json" \
    -H "x-source-token: YOUR_ASSIGNED_TOKEN" \
    -d '{
      "listen": true,
      "first_name": "Test",
      "last_name": "StandardLead",
      "phone": "5125550188",
      "email": "test.marcus@example.com",
      "state": "TX",
      "zipcode": "78704",
      "coverage_type": "Final Expense",
      "coverage_amount": "25000",
      "monthly_budget": "$85/mo",
      "notes": "Pre-flight validation test for standard lead ingestion.",
      "custom_fields": {
        "intent_score": 94,
        "test_source": "Partner QA Dispatcher"
      }
    }'
  ```

  ```typescript Node.js (Axios) theme={null}
  import axios from 'axios';

  const response = await axios.post(
    'https://api.3i.life/functions/v1/inbound-lead-gateway',
    {
      listen: true,
      first_name: 'Test',
      last_name: 'StandardLead',
      phone: '5125550188',
      email: 'test.marcus@example.com',
      state: 'TX',
      coverage_type: 'Final Expense',
      coverage_amount: '25000',
      notes: 'Pre-flight validation test for standard lead ingestion.',
    },
    {
      headers: {
        'Content-Type': 'application/json',
        'x-source-token': 'YOUR_ASSIGNED_TOKEN',
      },
    }
  );

  console.log('Test success:', response.data);
  ```

  ```python Python (Requests) theme={null}
  import requests

  url = "https://api.3i.life/functions/v1/inbound-lead-gateway"
  headers = {
      "Content-Type": "application/json",
      "x-source-token": "YOUR_ASSIGNED_TOKEN"
  }
  payload = {
      "listen": True,
      "first_name": "Test",
      "last_name": "StandardLead",
      "phone": "5125550188",
      "email": "test.marcus@example.com",
      "state": "TX",
      "coverage_type": "Final Expense",
      "coverage_amount": "25000"
  }

  response = requests.post(url, json=payload, headers=headers)
  print("Listen Response:", response.json())
  ```
</CodeGroup>

***

## Test Scenario 2: Scheduled Appointment Test

Verify your appointment timestamp formats, timezone resolution, and setter notes **without placing a phantom meeting on the agent's calendar**:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.3i.life/functions/v1/inbound-lead-gateway" \
    -H "Content-Type: application/json" \
    -H "x-source-token: YOUR_ASSIGNED_TOKEN" \
    -d '{
      "listen": true,
      "first_name": "Test",
      "last_name": "AppointmentBooking",
      "phone": "3055550143",
      "email": "test.appointment@example.com",
      "state": "FL",
      "status": "Scheduled",
      "schedule_type": "appointment",
      "scheduled_at": "2026-09-28T18:00:00.000Z",
      "appointment_timezone": "America/New_York",
      "setter_dialer_name": "Alexander Hayes (Setter Team Alpha)",
      "tags": ["Scheduled", "QA Test Appointment"],
      "notes": "APPOINTMENT TEST: Verifying appointment parser and calendar sync formatting without booking live lead.",
      "custom_fields": {
        "setter_id": "SETTER-442",
        "test_run": true
      }
    }'
  ```

  ```typescript Node.js (Axios) theme={null}
  import axios from 'axios';

  const response = await axios.post(
    'https://api.3i.life/functions/v1/inbound-lead-gateway',
    {
      listen: true,
      first_name: 'Test',
      last_name: 'AppointmentBooking',
      phone: '3055550143',
      email: 'test.appointment@example.com',
      state: 'FL',
      status: 'Scheduled',
      schedule_type: 'appointment',
      scheduled_at: '2026-09-28T18:00:00.000Z',
      setter_dialer_name: 'Alexander Hayes (Setter Team Alpha)',
      notes: 'APPOINTMENT TEST: Verifying appointment parser and calendar sync formatting.',
    },
    {
      headers: {
        'Content-Type': 'application/json',
        'x-source-token': 'YOUR_ASSIGNED_TOKEN',
      },
    }
  );

  console.log('Appointment Test Response:', response.data);
  ```

  ```python Python (Requests) theme={null}
  import requests

  url = "https://api.3i.life/functions/v1/inbound-lead-gateway"
  headers = {
      "Content-Type": "application/json",
      "x-source-token": "YOUR_ASSIGNED_TOKEN"
  }
  payload = {
      "listen": True,
      "first_name": "Test",
      "last_name": "AppointmentBooking",
      "phone": "3055550143",
      "state": "FL",
      "status": "Scheduled",
      "schedule_type": "appointment",
      "scheduled_at": "2026-09-28T18:00:00.000Z",
      "setter_dialer_name": "Alexander Hayes (Setter Team Alpha)",
      "notes": "APPOINTMENT TEST: Verifying appointment parser and calendar sync formatting."
  }

  response = requests.post(url, json=payload, headers=headers)
  print("Appointment Test Response:", response.json())
  ```
</CodeGroup>

***

## Expected Test Response (HTTP 200 OK)

When `"listen": true` is received, 3i validates your authentication, normalizes the fields, and confirms receipt with this exact response:

```json theme={null}
{
  "success": true,
  "listen": true,
  "message": "Sample received for mapping. Check your Lead Source in the app."
}
```

<Tip>
  **Verifying the Test in 3i CRM:**\
  Once you receive this response, have your 3i client or account manager open **Data & Integrations → Lead Sources**, select your lead source, and scroll to **Recent Payloads**. They will see your exact test payload and can confirm all fields and appointment data mapped cleanly.
</Tip>

***

## Machine-Readable Error Catalog

All error responses return both a human-readable `error` string and a standardized, machine-readable `error_code` for programmatic retry logic:

| HTTP Status | `error_code`           | Human Description                          | Resolution                                                                                   |
| :---------- | :--------------------- | :----------------------------------------- | :------------------------------------------------------------------------------------------- |
| **401**     | `MISSING_SOURCE_TOKEN` | `Missing x-source-token`                   | Supply your assigned token in the `x-source-token` header.                                   |
| **401**     | `INVALID_SOURCE_TOKEN` | `Invalid or inactive token`                | The token does not exist or has been disabled. Verify with your 3i account contact.          |
| **400**     | `MISSING_NAME`         | `Missing required field: name is required` | Neither `name` nor `first_name` was provided. Contact name is mandatory.                     |
| **400**     | `INVALID_JSON`         | `Invalid JSON body`                        | Malformed JSON body syntax. Validate quotes and brackets.                                    |
| **405**     | `METHOD_NOT_ALLOWED`   | `Method not allowed`                       | The endpoint requires HTTP `POST`.                                                           |
| **500**     | `INSERT_FAILED`        | `Failed to create lead`                    | Database constraint error. The `details` property contains failure info. Retry with backoff. |
| **500**     | `SERVER_ERROR`         | `Internal server error`                    | Temporary server glitch. Retry with exponential backoff.                                     |

***

## Recommended Retry Strategy

When dispatching leads from automated worker queues (BullMQ, Celery, SQS, Temporal):

<AccordionGroup>
  <Accordion title="Permanent Rejections (400, 401, 405)" icon="ban">
    **Do NOT retry automatically.** These indicate malformed payloads, missing contact names, or invalid authentication tokens. Route the job to your dead-letter queue (DLQ) for human inspection.
  </Accordion>

  <Accordion title="Transient Errors (429, 500, 502, 504)" icon="clock">
    **Automatically retry with exponential backoff.** Implement an exponential retry schedule:

    * Attempt 1: Wait 1s
    * Attempt 2: Wait 2s
    * Attempt 3: Wait 4s
    * Attempt 4: Wait 8s
    * Attempt 5: Wait 16s (max 30s cap)

    Always preserve the same `Idempotency-Key` across retries so that when the request succeeds, 3i safely dedupes the transaction without creating duplicate contacts.
  </Accordion>
</AccordionGroup>
