> ## Documentation Index
> Fetch the complete documentation index at: https://wiki.carewithemma.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks and Events: Push Triggers and Receive Outcomes

> Push events from your EMR, forms platform, or payment system to Emma and receive structured outcome notifications when workflows complete.

Webhooks let your systems push events to Emma as they happen. When Emma receives a supported event, it automatically starts the matching workflow. Emma also fires outbound webhook events to your configured URL when a workflow completes, so your systems stay up to date without polling.

## How webhooks work

<Steps>
  <Step title="Register your outbound URL">
    Go to **Emma → Integrations → No-Code Automation**. Add the URL where Emma should send outcome events and copy your inbound webhook URLs for use in the next step.
  </Step>

  <Step title="Subscribe in your platform">
    In your forms platform, EMR, or payment system, subscribe to the relevant event (for example, `forms.abandoned`) and point it at your Emma inbound URL.
  </Step>

  <Step title="Emma receives the event">
    Emma parses the payload, matches it to the configured workflow, and starts execution automatically.
  </Step>

  <Step title="Emma sends the outcome">
    When the workflow completes, Emma POSTs the outcome event to your registered outbound URL.
  </Step>
</Steps>

## Inbound events Emma accepts

| Event | Trigger |
| - | - |
| `forms.abandoned` | A patient dropped off before completing a form or checkout |
| `forms.completed` | A patient completed a form (cancels any pending recovery) |
| `appointment.created` | A new appointment was booked |
| `appointment.approaching` | An appointment is coming up soon |
| `payment.failed` | A payment transaction failed |
| `prescription.status_changed` | A prescription or fulfillment status changed |
| `patient.follow_up_required` | A follow-up action is needed for a patient |

### Inbound event URLs and payloads

Emma exposes per-clinic inbound webhook URLs. Use the URLs from the Integrations page to point your platform at the correct endpoint for each event type.

```http theme={null}
POST /api/n8n/webhook/{clinicId}/forms-abandoned
x-n8n-secret: <your-inbound-secret>
Content-Type: application/json

{
  "event": "forms.abandoned",
  "tenant_id": "tenant_7c21...",
  "sent_at": "2026-09-24T14:05:00Z",
  "data": {
    "session_id": "sess_8f2c...",
    "form_id": "form_weightcare_01",
    "form_name": "Weight care intake",
    "last_page_reached": 6,
    "total_pages": 7,
    "completion_percentage": 85,
    "last_activity_at": "2026-09-24T13:40:00Z",
    "draft_age_hours": 1,
    "abandoned_at": "2026-09-24T14:05:00Z",
    "abandoned_at_checkout": true,
    "resume_url": "https://your-platform.example/resume/sess_8f2c...",
    "partial_form_data": {
      "phi_first_name": "Jordan",
      "phi_last_name": "Lee",
      "phi_email": "jordan@example.com",
      "phi_phone": "+15551234567",
      "selectedProducts": [{ "productName": "Starter plan", "unitPrice": 199 }]
    }
  }
}
```

```http theme={null}
POST /api/n8n/webhook/{clinicId}/forms-completed
x-n8n-secret: <your-inbound-secret>
Content-Type: application/json

{
  "event": "forms.completed",
  "tenant_id": "tenant_7c21...",
  "data": {
    "session_id": "sess_8f2c..."
  }
}
```

<Note>
  **Required fields.** For `forms-abandoned`, Emma rejects the request with `400` unless `tenant_id` and these `data` fields are present: `session_id`, `form_id`, `form_name`, `abandoned_at`, `last_activity_at`, `completion_percentage`, `last_page_reached`, `total_pages`, `draft_age_hours`. For `forms-completed`, only `data.session_id` is required. The request is accepted without `partial_form_data`, but Emma can't place the call unless it includes `phi_phone`.
</Note>

## Securing inbound webhooks

Emma uses a shared secret to verify that inbound requests originate from a trusted source. Each inbound webhook URL has an associated secret generated on the Integrations page. Your platform must include this secret in every request:

```http theme={null}
x-n8n-secret: <your-inbound-secret>
```

<Warning>
  Always validate the inbound secret before processing a webhook payload. Requests missing or presenting a wrong secret should be rejected with a 401.
</Warning>

## Outbound webhook events

When a workflow finishes, Emma POSTs an outcome event to your registered outbound URL. The payload includes the clinic, a timestamp, and structured outcome data you can use to update your own records or trigger downstream actions.

### `recovery_case.created`

Emma fires this event as soon as it creates a recovery case — before any outreach attempt is made. Use it to log or display the pending case in your system.

```json theme={null}
{
  "event": "recovery_case.created",
  "clinicId": "clinic_abc123",
  "sentAt": "2026-09-24T14:20:05Z",
  "data": {
    "recoveryCaseId": "rc_41d0...",
    "sessionId": "sess_8f2c...",
    "patientFirstName": "Jordan",
    "patientLastName": "Lee"
  }
}
```

### `recovery_case.outcome`

Emma fires this event when a recovery workflow reaches a terminal state. Use it to update your system of record with the final outcome.

```json theme={null}
{
  "event": "recovery_case.outcome",
  "clinicId": "clinic_abc123",
  "sentAt": "2026-09-24T14:27:41Z",
  "data": {
    "recoveryCaseId": "rc_41d0...",
    "sessionId": "sess_8f2c...",
    "recoveryStatus": "RECOVERED"
  }
}
```

## Recovery status values

| `recoveryStatus` | Meaning |
| - | - |
| `RECOVERED` | Patient agreed to finish; resume link sent |
| `FOLLOW_UP_REQUIRED` | Patient wants a callback or needs more time |
| `PRICING_ESCALATION` | Needs someone from the billing team |
| `CLINICAL_ESCALATION` | Needs someone from the care team |
| `PATIENT_NOT_INTERESTED` | Patient declined to continue |
| `PATIENT_NOT_REACHED` | Patient could not be reached |
| `ALREADY_COMPLETED` | Patient finished before Emma called |

## Idempotency

Emma deduplicates incoming events by session ID. Sending the same `forms.abandoned` event twice for the same session creates only one recovery case — so you don't need to worry about accidental duplicate triggers from your platform.

## When to use webhooks

<Tip>
  Use webhooks when your system needs to notify Emma that something happened. If you need to request an action on demand and wait for a response, use the [REST API](/rest-api) instead.
</Tip>
