REST API
JSON over HTTPS at https://rows.page/api/v1, with CORS open to every origin.
The OpenAPI 3.1 description is at /openapi.json.
Authentication
Send Authorization: Bearer <credential>. The prefix decides what it is.
- Dataset token
rpt_+ 32 characters. Returned once when a dataset is created, and in the owner link. Grants new versions, findings, edits and delete for that one dataset.- API key
rpk_+ 32 characters. Created on your account page and shown once. Grants everything on your account's datasets, plus keyed pushes.- Firebase ID token
- What the signed-in browser sends. You won't need it from scripts.
Keeping an anonymous dataset takes both: your account in Authorization and the dataset token in X-Rows-Token.
Endpoints
Paths are relative to /api/v1.
- POST /push
Push a file (raw body). Always answers JSON.
Auth: optional
- GET /datasets/<id>
Meta, versions, findings and a preview of the latest version.
Auth: public or owner
- PATCH /datasets/<id>
Change
title,summary,id_columnorvisibility.Auth: owner
- DELETE /datasets/<id>
Delete the dataset.
Auth: owner
- GET /datasets/<id>/versions/<n>
Version meta and preview.
Auth: public or owner
- GET /datasets/<id>/versions/<n>/data
Raw bytes, with Range support. Also at
/<id>/v<n>/raw.<format>.Auth: public or owner
- POST /datasets/<id>/findings
Pin a finding:
{title, note, q, sort, cols, sql, version, row_count}.Auth: owner
- PATCH, DELETE /datasets/<id>/findings/<fid>
Edit or remove a finding.
Auth: owner
- POST /datasets/<id>/keep
Attach an anonymous dataset to your account.
Auth: account + X-Rows-Token
- POST /datasets/<id>/report
Report abuse.
Auth: none
- GET /datasets
Your datasets, cursor paging.
Auth: account
- GET /me
Account, plan, limits and usage.
Auth: account
- GET, POST, DELETE /keys, /keys/<id>
Manage API keys.
Auth: signed in
- POST, PUT /uploads, /uploads/<id>/<part>, /uploads/<id>/complete
Multipart upload for files over 100 MB, in 64 MB parts.
Auth: Pro or Max
- GET /fetch?url=
Capped proxy for remote files that block CORS.
Auth: none
- GET /health
{ok, version}Auth: none
Push
POST /api/v1/push takes the file as the raw request body, with parameters in the query string or X-Rows-* headers. It always answers JSON. PUT to https://rows.page/<filename> is the same push for curl -T.
curl --data-binary @orders.csv \
-H "Authorization: Bearer rpk_..." \
"https://rows.page/api/v1/push?key=nightly-orders&id_column=order_id&title=Nightly%20orders"Push response
- id string
- Dataset id.
- version number
- Version number, 1 for a new dataset.
- url string
- Dataset page. Public datasets open for anyone with the link.
- owner_url string | null
- Page URL with
#t=<token>, which opens with owner controls. Creation only. - token string | null
- Dataset token (
rpt_...) for re-pushes and findings. Creation only, so store it. - format string
- Detected format.
- bytes number
- File size in bytes.
- rows number | null
- Row count, null if it couldn't be counted.
- rows_exact boolean
- False when
rowsis an estimate. - columns array
{name, type}per column. Nested fields use dot paths.- expires_at string | null
- When an anonymous dataset gets deleted. Null once it's kept.
- unchanged boolean
- True when the file matched the latest version, so no version was added.
- changes object | null
- On a new version:
previous_version,rows_delta,columns_added,columns_removed,diff_url. - keep object | null
{required, url, message}: whether the dataset still needs keeping, and where.- limits object
plan,max_file_bytes,datasets_used,datasets_limit.
Errors
Errors share one shape: error is a stable code, message is for humans, and request_id helps us find the request.
{
"error": "upgrade_required",
"message": "Free accounts keep 10 datasets. Pro keeps 100.",
"reason": "keep_limit",
"plan_needed": "pro",
"upgrade_url": "https://rows.page/pricing",
"request_id": "9f2c1a7b"
}- 201
- New dataset created.
- 200
- New version added, or
unchanged: truewhen the file matches the latest version. - 400 bad_format
- The body isn't readable CSV, TSV, JSON, JSONL or Parquet.
- 401 / 403
- Missing, invalid or wrong dataset token or API key.
- 402 upgrade_required
- A plan limit was hit. The body has
reason,plan_neededandupgrade_url. - 413 too_large
- Over the request or plan size cap. The body names your cap and the multipart API.
- 429
- Rate limited. Retry after
Retry-Afterseconds.