Files
File interface: S3 and SFTP drops
The zero-integration way in: publish your catalog, rate cards, and avails as file drops, and return delivery posts through the same channel. A drop is a set of files landed under your prefix, over S3 or SFTP, registered by a manifest. Accepted formats per type: csv, parquet, xlsx, json.
s3://switchboard-ingest/{seller_id}/{drop_id}/
catalog.csv
rates.csv
avails.csv
manifest.json
Ingestion is asynchronous; a clean drop publishes in minutes. The result lands back in the drop as success.json, or as errors.json naming every rejected row and its code:
{
"drop_id": "drop_2026-W40-001",
"status": "partial",
"rows_written": 840,
"errors": [
{
"file": "avails.csv",
"row": 147,
"error_code": "UNKNOWN_PACKAGE_ID",
"value": "acme-fringe-old"
}
]
}
catalog.integrity_failed event with the conflict report attached.Register a file drop
POST/v1/me/files/manifestcatalog:write
Register the manifest for a landed drop; ingestion starts on registration.
Request body
| Field | Type | Description |
|---|---|---|
schema_version required | string | Manifest schema version. Current version: 1.0. |
drop_id required | string | The drop the files landed under. |
effective | object | Coverage window the drop asserts: {start, end}, ISO dates. |
files[] required | array of object | One entry per landed file. |
files[].filename required | string | File name inside the drop. |
files[].type required | enum | What the file carries: catalog, rate_cards, avails, or delivery_posts. |
files[].format | enum | csv, parquet, xlsx, or json. Default: inferred from the file extension. |
files[].sha256 required | string | Checksum of the landed file; the file's identity for idempotency. |
A manifest for a full catalog drop:
{
"schema_version": "1.0",
"drop_id": "drop_2026-W41-001",
"effective": {
"start": "2026-10-05",
"end": "2026-12-27"
},
"files": [
{
"filename": "catalog.csv",
"type": "catalog",
"format": "csv",
"sha256": "9f86d081..."
},
{
"filename": "rates.csv",
"type": "rate_cards",
"format": "csv",
"sha256": "b94f6f12..."
},
{
"filename": "avails.csv",
"type": "avails",
"format": "csv",
"sha256": "3a7bd29c..."
}
]
}
sha256 values all match an already-processed drop replays the original result instead of reprocessing.Response
Registration is accepted and processing starts; results land in the drop as success.json or errors.json.
202 Response
{
"drop_id": "drop_2026-W41-001",
"status": "processing",
"results_uri": "s3://switchboard-ingest/acme/drop_2026-W41-001/"
}
Errors
| Status | Code | When |
|---|---|---|
| 404 | NOT_FOUND | drop_id does not match a landed drop under your prefix. |
| 422 | INVALID_INPUT | A sha256 does not match the landed file, or a manifest entry names a file missing from the drop. |
EDI (agency and traffic systems)
EDI is the TV industry's electronic paper trail, and it runs in both directions: station traffic and billing systems generate it (invoices, as-run detail), and agency systems of record (Prisma, Strata) consume it. Switchboard plugs into both ends of that flow.
Out, for buyers. If your billing lives in an agency system of record, Switchboard delivers confirmed orders over the established interchange (structured XML via the industry's email transport), so order and billing records land in the same place your current orders land. Include your estimate_id in buyer_metadata and it is echoed on the delivery, so your billing system can match the record.
In, for sellers. Your traffic system already produces EDI invoices and as-run log times. Point those feeds at Switchboard like any other file drop and they attach to orders as reconciliation inputs: air dates, times, and copy against what was booked, in the paper your plant already prints.