Documentation

Bulk Import API

Import many speakers, sessions, or sponsors in a single request.

Import up to 200 records of one type per request. Requires the standard authentication headers and the write scope matching the type you send - speakers:write, sessions:write or sponsors:write.

The API is rate limited to 300 requests per minute, so loading a large programme one record at a time stalls partway through. This endpoint moves that into a handful of calls.


POST /bulkUpsert

{
  "type": "session",
  "items": [
    { "name": "Opening keynote", "date": "2026-09-01", "timeStart": "09:00", "track": 0 },
    { "name": "Scaling workshop", "date": "2026-09-01", "timeStart": "11:00", "track": 1 },
    { "sessionId": "s99", "capacity": 250 }
  ]
}
Field Type Notes
type enum speaker, session or sponsor.
items array 1 to 200 records. Each takes the same fields as the matching single-record endpoint.

As with the single-record endpoints, an item without its id field is created and an item with one is edited.


Valid rows are written even when others fail

A 200-row import should not be lost because row 137 has a bad date. Every item is validated independently; the good ones are written and the response names the rows that were not, by index.

{
  "status": "partial",
  "type": "session",
  "written": 2,
  "failed": 1,
  "results": [
    { "index": 0, "status": "created", "id": "s100" },
    { "index": 1, "status": "created", "id": "s101" },
    {
      "index": 2,
      "status": "error",
      "errors": ["'track' must be at most 2 (received 7) - the valid range comes from session track (the event's trackArray)."]
    }
  ]
}

status is success when everything landed and partial when some rows failed. Fix the failed rows and send just those again.

To check an import before committing to it, add ?dryRun=1: every row is validated and nothing is written.


Limits and exclusions

  • 200 items per call. Send larger imports in batches.
  • Rich content pages are not accepted here. A session’s or sponsor’s content sections can link to other speakers and sponsors, and each of those links has to be checked - which would make a large import far slower. Import the records first, then add their content with /upsertSession or /upsertSponsor. Sending content on a row fails that row with a message saying so, rather than dropping it quietly.
  • One type per call. Permissions are per type, so a key that may write sessions cannot bulk-write speakers.