Developer Guide · Guides

External data

Push any JSON from your platform (students, subscriptions, orders, appointments) and Inboxi links it to the customer by phone, shows it to agents next to the chat, and gives it to the AI agent so it can recognise and help the customer.

External data is a flexible store for records that live in your system. You decide the shape. Inboxi only needs to know where it came from (source), what kind of record it is (dataType), who it belongs to (contactIdentifier) and, ideally, your own ID for it (externalId).

Concepts

FieldWhat it isExample
sourceYour platform name. Use the same value everywhere.academy
dataTypeThe kind of record. Free text; one schema is discovered per source + type.student, enrollments, grades
contactIdentifierThe customer's phone in international format (or email). This links the record to the chat.201012345678
externalIdYour stable ID for the record. Makes pushes upserts instead of inserts.enrollment_3341
dataAny JSON object.{ "course_name": "Math", "status": "active" }
Your platform
Change in a record
push
POST /external-data
Upsert by externalId + dataType
matched by phone
Inbox sidebar
Agents see it next to the chat
context
AI agent
Recognises and answers the customer

Push a record (upsert)

POST/api/v1/external-dataCreate or update one record (permission: external_data)

When externalId is present and a record with the same externalId and dataType already exists, it is updated in place. That means you can push the same entity on every change, and you can store several record types for one entity (a student and its grades keyed by the same ID) without them overwriting each other.

curl -X POST https://inboxi.app/api/v1/external-data \
  -H "X-API-Key: $INBOXI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "academy",
    "dataType": "enrollments",
    "contactIdentifier": "201012345678",
    "externalId": "enrollment_3341",
    "data": {
      "student_name": "Youssef Mohamed",
      "course_name": "Mathematics - Grade 12",
      "status": "active",
      "start_date": "2026-10-01",
      "expiry_date": "2027-06-30"
    }
  }'

Optional fields schemaVersion, sourceCreatedAt and sourceUpdatedAt let you keep your own versioning and timestamps on the record. Every push fires the external_data.received webhook.

Names update the chat
Records with dataType parent or student also update the name of the matching chat (fromparent_name/student_name or name), so agents see a real name instead of a phone number.

Bulk push

POST/api/v1/external-data/bulkUp to 500 records of one source + dataType
json
{
  "source": "academy",
  "dataType": "student",
  "records": [
    { "contactIdentifier": "201012345678", "externalId": "student_9871", "data": { "student_name": "Youssef", "grade": "12", "status": "active" } },
    { "contactIdentifier": "201099887766", "externalId": "student_9872", "data": { "student_name": "Sara",    "grade": "11", "status": "active" } }
  ]
}

// Response
{ "success": true, "created": 1, "updated": 1, "errors": [] }

Use bulk for initial imports and nightly syncs. Records are processed one by one; a bad record is reported in errors without failing the rest. Split larger sets into batches of 500 and stay under the rate limit.

Auto-discovered schemas

Inboxi inspects incoming data and keeps a schema per source + dataType: each field's key, type, readable label and a sample value (nested objects one level deep). New fields are merged in as they appear. Read them with GET /api/v1/external-data/schemas (optionally ?source=academy).

json
{
  "success": true,
  "data": [{
    "source": "academy",
    "dataType": "enrollments",
    "recordCount": 1840,
    "fields": [
      { "key": "student_name", "type": "string", "label": "student name", "sampleValue": "Youssef Mohamed" },
      { "key": "status",       "type": "string", "label": "status",       "sampleValue": "active" }
    ]
  }]
}

Read, browse and delete

  • GET /api/v1/external-data filters by source, dataType, contactIdentifier or externalId, paginated (50 per page by default).
  • GET /api/v1/external-data/contact/:identifier returns every record for one person, grouped by source and type. Phone formats are matched flexibly (with or without +).
  • DELETE /api/v1/external-data/:id removes one record; DELETE /api/v1/external-data/source/:source removes everything from a source.

Agents and admins can browse everything your platform pushed in Settings › Developer Hub › External Data:

inboxi.app/settings/developer
External Data shows every record received through the API.
  1. 1External Data tab.
  2. 2Filter by source.
  3. 3Filter by data type.
  4. 4Search by the contact's phone or email.

How the AI agent uses external data

When a customer writes in, Inboxi looks up external data for the customer's phone number and adds it to the AI agent's context before it answers. No extra configuration is needed.

  • Recognition: a record with dataType: "provider" marks the person as a registered user of your platform and supplies their name, so the agent greets them as a known customer instead of asking who they are.
  • Catalogues and history: products and services records with an items array, and an orders record with orders/bookings summaries, are given to the agent as structured lists.
  • Everything else: any other dataType (enrollments, subscriptions, tickets, policies…) is grouped by type and included too, up to 25 records per type, so the agent can answer “is my subscription active?” or “what is my next lesson?”.
  • Links: URLs inside your records are passed to the agent safely, so it can share a deep link (course page, invoice, report) without mangling it.
Match the phone exactly
The lookup is by phone. Use the customer's WhatsApp number in international format ascontactIdentifier (for example 201012345678, not 01012345678). If the record is keyed to a different number than the one chatting, the agent will not see it.

For data that is too large or too volatile to push in advance, let the agent fetch it live with a read-only remote action.