Webhooks

Webhooks deliver real-time HTTP notifications when extractions or entity credentials change.

Delivery flow

sequenceDiagram
    autonumber
    participant API as Meefi API
    participant App as Your webhook endpoint
    participant Queue as Your job queue

    Note over API: extraction.update or entity.update
    API->>+App: POST /hooks/meefi
Authorization: Bearer {token} App->>App: Verify bearer token alt Token valid App->>Queue: Enqueue side effects App-->>-API: 2xx (quick ack) Queue->>Queue: Sync invoices, alerts, etc. else Token invalid App-->>API: 401 Unauthorized end Note over API,App: Non-2xx may trigger retries
— handlers must be idempotent

Register a webhook

POST /v1/webhooks

{
  "url": "https://your-app.example.com/hooks/meefi",
  "events": []
}
Field Description
url HTTPS endpoint that accepts POST requests
events Optional filter (currently all organization events are sent)

Response includes:

Field Description
id Webhook UUID
url Callback URL
token Bearer token included in delivery requests
events Subscribed events array

Store the token securely. It is used to authenticate incoming webhook calls.

List and manage

  • GET /v1/webhooks — list all webhooks
  • GET /v1/webhooks/{id} — get one webhook
  • DELETE /v1/webhooks/{id} — remove subscription (204)

Delivery format

Each event is POSTed as JSON:

{
  "event": "extraction.update",
  "source": "extractions/a1ef89c2-9226-498d-8adf-38fc1e97cbcd",
  "resource": {
    "type": "Extraction",
    "id": "a1ef89c2-9226-498d-8adf-38fc1e97cbcd",
    "path": "extractions/a1ef89c2-9226-498d-8adf-38fc1e97cbcd"
  },
  "object": {
    "status": "finished",
    "started_at": "2026-06-03T15:50:05.000000Z",
    "finished_at": "2026-06-03T15:52:18.000000Z",
    "entity": {
      "id": "9e08bb63-f6c1-44cf-a5b5-a92967cb172d",
      "tax_id": "…",
      "name": "…"
    }
  }
}

Authentication

Requests include:

Authorization: Bearer {webhook.token}

Verify this token on your endpoint before processing the payload.

Event types

Event When fired object contents
extraction.update Extraction starts, finishes, or fails Status, timestamps, nested entity summary
entity.update Credential validation completes or credential status changes credential_status, entity identifiers
flowchart LR
    subgraph Events
        E1[extraction.update]
        E2[entity.update]
    end
    subgraph Triggers
        T1[status pending → running → finished]
        T2[credential pending → valid / invalid]
    end
    T1 --> E1
    T2 --> E2

Recommended handler pattern

flowchart TD
    A[Receive POST] --> B{Bearer token valid?}
    B -->|No| C[Return 401]
    B -->|Yes| D[Parse JSON]
    D --> E{event type}
    E -->|extraction.update| F{object.status}
    F -->|finished| G[Queue invoice sync]
    F -->|failed| H[Alert operations]
    E -->|entity.update| I[Update credential cache]
    G --> J[Return 2xx immediately]
    H --> J
    I --> J

Retry behavior

Failed deliveries may be retried. Implement idempotent handlers because the same event may be delivered more than once.

Local development

Use a tunneling tool (ngrok, Cloudflare Tunnel) to expose a local URL, then register it via POST /v1/webhooks.

Example handler (Node.js):

app.post('/hooks/meefi', (req, res) => {
  const token = req.headers.authorization?.replace('Bearer ', '');
  if (token !== process.env.MEEFI_WEBHOOK_TOKEN) {
    return res.status(401).send('Unauthorized');
  }

  const { event, object } = req.body;

  if (event === 'extraction.update' && object.status === 'finished') {
    queueInvoiceSync(object.entity.id);
  }

  res.sendStatus(204);
});