Get exhibitor data in.
Bring your exhibitor roster into Standwyse from wherever it lives today — a spreadsheet, your CRM, or your customer data platform. Two ways in, both writing through the same idempotent path so they never duplicate rows.
Two ways in
CSV import — for a one-off or occasional load, export your roster as CSV and upload it from the organiser Exhibitors page. Map your columns, preview, and commit. Re-uploading an updated file updates the same accounts rather than creating duplicates.
Ingestion API — for an automated, repeatable sync from your own systems. POST a batch of exhibitors to /api/ingest/exhibitors. This is the same endpoint a Zapier app or a partner connector builds against — the full machine-readable contract is the interactive API reference.
Authentication
The API authenticates with a per-tenant API key. Generate one from the organiser Exhibitors page — it is shown once at creation, so copy it somewhere safe. Send it as a bearer token on every request:
Authorization: Bearer swk_live_your_key_hereA key is scoped to the organisation that created it, so it can only ever write into that organisation’s events. Revoke a key at any time from the same page; a revoked key immediately returns 401.
Idempotency — upsert by external_id
Every exhibitor row carries an external_id: your system’s stable id for that company (a CRM record id, for example). Standwyse keys on it, so sending the same external_id again updates the existing account instead of creating a second one. That makes the endpoint safe to retry and safe to run on a schedule — a nightly full-roster push converges rather than piling up duplicates.
Send a batch
- Generate an API keyOn the organiser Exhibitors page, create an ingestion key and copy it.
- POST your exhibitorsSend a batch of up to 1000 rows to /api/ingest/exhibitors for one event_slug.
- Read the resultapplied tells you how many rows were saved; failed lists any rows that were rejected, by line and field.
curl -X POST https://standwyse.com/api/ingest/exhibitors \
-H "Authorization: Bearer swk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"event_slug": "aurora-tech-expo",
"exhibitors": [
{
"external_id": "crm-8842",
"account_name": "Helix Robotics Ltd",
"contact_email": "ops@helixrobotics.example.com",
"reference_code": "EX-204",
"package_name": "Premium 6x4"
}
]
}'const res = await fetch("https://standwyse.com/api/ingest/exhibitors", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.STANDWYSE_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
event_slug: "aurora-tech-expo",
exhibitors: [
{
external_id: "crm-8842",
account_name: "Helix Robotics Ltd",
contact_email: "ops@helixrobotics.example.com"
}
]
})
});
const result = await res.json();
// { "applied": 1, "inserted": 1, "updated": 0, "failed": [] }Response & partial failures
Good rows always apply, even when others fail. The response reports how many rows were saved and lists every rejected row by its 1-based position in the batch — nothing is silently dropped.
{
"applied": 2,
"inserted": 1,
"updated": 1,
"failed": [
{ "line": 3, "field": "contact_email", "message": "Invalid email" }
]
}applied is inserted + updated. Each entry in failed names the offending line, field, and a human-readable message.
Errors
Whole-request problems return a single error envelope with the matching HTTP status:
{ "error": "Invalid or revoked API key." }- 400 — body isn’t valid JSON, or fails top-level validation
- 401 — missing, invalid, or revoked API key
- 404 — no event with that slug in this key’s organisation
- 413 — request body exceeds the size cap
- 429 — rate limit exceeded (see the Retry-After header)
CSV column spec
The importer accepts any column order and maps common header names automatically. The downloadable template on the Exhibitors page uses these columns:
external_id— required. Your stable id; the idempotency key.account_name— required. The exhibiting company’s name.contact_email— optional. Primary contact email.reference_code— optional. Your booking/reference code.package_name— optional. Stand or sponsorship package.status— optional. Defaults toactive.