API Reference · Endpoints

External data

Push structured records from your platform into Inboxi, query them, and delete them. Any JSON shape is accepted and field schemas are discovered automatically.

External data lets your platform store any JSON record in Inboxi: grades, attendance, subscriptions, invoices, bookings. Records are grouped by source (your platform) and dataType (the kind of record), and can be linked to a customer by phone or email so agents and AI agents see them next to the conversation. Background and examples: External data guide.

EndpointPermission
POST /api/v1/external-dataexternal_data
POST /api/v1/external-data/bulkexternal_data
GET /api/v1/external-dataread
GET /api/v1/external-data/contact/:identifierread
GET /api/v1/external-data/schemasread
DELETE /api/v1/external-data/:idwrite
DELETE /api/v1/external-data/source/:sourcewrite

Push a record

POST/api/v1/external-dataCreate or update one record
ParameterTypeRequiredDescription
sourcestringrequiredYour platform's name, for example moodle or salesforce.
dataTypestringrequiredKind of record, for example grades or attendance.
dataobjectrequiredAny JSON object.
contactIdentifierstringoptionalPhone or email linking the record to a customer.
externalIdstringoptionalYour id for the record. With it, a push updates the existing record with the same externalId and dataType instead of creating a duplicate.
schemaVersionstringoptionalYour schema version label. Default 1.0.
sourceCreatedAtstringoptionalWhen the record was created in your platform (ISO 8601).
sourceUpdatedAtstringoptionalWhen the record was last changed in your platform (ISO 8601).
curl -X POST "https://inboxi.app/api/v1/external-data" \
  -H "X-API-Key: inx_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "moodle",
    "dataType": "grades",
    "contactIdentifier": "+201012345678",
    "externalId": "grade_9001",
    "data": {
      "studentName": "Ahmed Ali",
      "course": "Mathematics",
      "grade": 95,
      "semester": "Spring 2026"
    }
  }'

Returns 201 with the stored record:

json
{
  "success": true,
  "data": {
    "id": 1203,
    "source": "moodle",
    "dataType": "grades",
    "contactIdentifier": "+201012345678",
    "externalId": "grade_9001",
    "data": { "studentName": "Ahmed Ali", "course": "Mathematics", "grade": 95, "semester": "Spring 2026" },
    "schemaVersion": "1.0",
    "sourceCreatedAt": null,
    "sourceUpdatedAt": null,
    "createdAt": "2026-03-18T12:00:00.000Z",
    "updatedAt": "2026-03-18T12:00:00.000Z"
  }
}
Names in the inbox stay in sync
When dataType is parent or student and the record has a parent_name/student_name (or name), Inboxi renames the customer's latest conversation with that phone to match.

Every successful push fires an external_data.received webhook. A missing field returns 400 with "error": "Required fields: source, dataType, data".

Push records in bulk

POST/api/v1/external-data/bulkUp to 500 records per request
ParameterTypeRequiredDescription
sourcestringrequiredPlatform name, shared by every record.
dataTypestringrequiredRecord type, shared by every record.
recordsarrayrequiredUp to 500 items. Each takes data and optionally contactIdentifier, externalId, schemaVersion, sourceCreatedAt, sourceUpdatedAt.
curl -X POST "https://inboxi.app/api/v1/external-data/bulk" \
  -H "X-API-Key: inx_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "moodle",
    "dataType": "attendance",
    "records": [
      {
        "contactIdentifier": "+201012345678",
        "externalId": "att_1",
        "data": {
          "date": "2026-03-18",
          "status": "present"
        }
      },
      {
        "contactIdentifier": "+201098765432",
        "externalId": "att_2",
        "data": {
          "date": "2026-03-18",
          "status": "absent"
        }
      }
    ]
  }'

Returns 201 with counts. A record that fails does not stop the others; it is listed in errors:

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

More than 500 records returns 400 with "error": "Maximum 500 records per bulk request". The schema is discovered from the first record of the batch.

Query records

GET/api/v1/external-dataFilter and page through records, newest first
ParameterTypeRequiredDescription
sourcestringoptionalFilter by source.
dataTypestringoptionalFilter by data type.
contactIdentifierstringoptionalExact match on the linked phone or email.
externalIdstringoptionalExact match on your record id.
pagenumberoptionalPage number. Default 1.
limitnumberoptionalResults per page. Default 50, max 200.
curl "https://inboxi.app/api/v1/external-data?source=moodle&dataType=grades&limit=20" \
  -H "X-API-Key: inx_live_your_api_key"
json
{
  "success": true,
  "data": [ { "id": 1203, "source": "moodle", "dataType": "grades", "data": { ... }, ... } ],
  "pagination": { "page": 1, "limit": 20, "total": 312, "totalPages": 16 }
}

Get a contact's data

GET/api/v1/external-data/contact/:identifierAll records for one customer, grouped by source

Phone matching is forgiving: +201012345678, 201012345678 and 01012345678 all find the same records. URL-encode the identifier (+ becomes %2B).

ParameterTypeRequiredDescription
identifierstringrequiredPath parameter: phone or email used as contactIdentifier.
curl "https://inboxi.app/api/v1/external-data/contact/%2B201012345678" \
  -H "X-API-Key: inx_live_your_api_key"
json
{
  "success": true,
  "records": [ { "id": 1203, "source": "moodle", "dataType": "grades", ... } ],
  "grouped": {
    "moodle": {
      "grades": [ { "id": 1203, ... } ],
      "attendance": [ { "id": 1310, ... } ]
    }
  }
}

Get discovered schemas

GET/api/v1/external-data/schemasFields Inboxi discovered per source and data type
ParameterTypeRequiredDescription
sourcestringoptionalOnly schemas of this source.
curl "https://inboxi.app/api/v1/external-data/schemas?source=moodle" \
  -H "X-API-Key: inx_live_your_api_key"
json
{
  "success": true,
  "data": [
    {
      "id": 14,
      "source": "moodle",
      "dataType": "grades",
      "fields": [
        { "key": "studentName", "type": "string", "label": "student Name", "sampleValue": "Ahmed Ali" },
        { "key": "grade", "type": "number", "label": "grade", "sampleValue": "95" }
      ],
      "recordCount": 312,
      "lastSyncAt": "2026-03-18T12:00:00.000Z"
    }
  ]
}

New fields are merged in as they appear. Nested objects are described one level deep (for example address.city).

Delete a record

DELETE/api/v1/external-data/:idDelete one record by its Inboxi id
curl -X DELETE "https://inboxi.app/api/v1/external-data/1203" \
  -H "X-API-Key: inx_live_your_api_key"
json
{ "success": true }

Returns 404 with "error": "Record not found" if the id is not in your workspace.

Delete a whole source

DELETE/api/v1/external-data/source/:sourceDelete every record and schema of a source
curl -X DELETE "https://inboxi.app/api/v1/external-data/source/moodle" \
  -H "X-API-Key: inx_live_your_api_key"
json
{ "success": true, "deletedCount": 312 }
This cannot be undone. The discovered schemas of the source are removed too.