Skip to main content
Streams one sheet’s validated data as a CSV, addressed by template slug. This is synchronous — there’s no run to poll. Columns come out in template order, RFC 4180-escaped, and the body is streamed (gzip-compressed when your client sends Accept-Encoding: gzip). One call exports one sheet. To export a whole workbook, request each template’s slug in turn.

Authentication

Requires an x-api-key header. See Authentication.

Path & query

template_slug
string
required
The slug of the template whose sheet you want, with a .csv suffix — e.g. contacts.csv. List your templates for slugs.
filter
string
default:"valid"
Which rows to include:
  • valid (default) — only fully clean rows. Any row with even one cell that failed validation is excluded entirely, so the count can be lower than the sheet’s total.
  • all — every row, including those with invalid cells.
  • invalid — only the flagged rows (those with at least one invalid cell) — useful for surfacing what needs fixing.

Response

200 OK with Content-Type: text/csv; charset=utf-8 and a Content-Disposition attachment header. The body is streamed. An X-Total-Records header reports how many records match the filter. When the request advertises gzip, the response is gzip-encoded (Content-Encoding: gzip).

Errors

Example

Into your own storage

The endpoint hands you the file in the HTTP response — Vern doesn’t push it anywhere. To land the clean CSV in your own bucket, pull it from your backend and pipe it straight into object storage. The body streams, so you never have to buffer the whole file:
Any S3-compatible store (R2, MinIO, Spaces) works the same way. Keep your x-api-key server-side — run this from your backend, never the browser. Vern never receives your storage credentials; your backend relays the bytes.
Prefer Vern to deliver directly into a bucket you own — via a presigned URL or stored bucket credentials — instead of relaying it yourself? That’s not available today. Tell us at vish@vern.so if you’d use it.

Next