Send up to 1,000 link objects as { "links": [ … ] } to POST /v1/links/bulk, or upload a CSV file (multipart field file, UTF-8, at most 10 MB and 10,000 rows) to POST /v1/links/import. The CSV header names the columns destination_url (required), slug, title and description; any other column, bad quoting or too many rows fails with 422 csv_invalid and details naming the lines. Both need the links:write scope, a verified email and the Pro plan or above (otherwise 403 feature_not_in_plan, param: bulk_csv), and both accept an Idempotency-Key (a retry returns the same job). They answer 202 { "job_id": "job_…", "status": "queued", "total": 250 }.
Poll GET /v1/jobs/{id} every few seconds for status (queued, processing, paused, completed, failed), progress { total, done, failed } and the first 100 row errors, then download GET /v1/jobs/{id}/results (CSV: row, status, short_url, link_id, destination_url, slug, error_code, error_message). Each row follows the normal create rules: a row over your monthly link quota fails with plan_limit_reached (the others still succeed, and existing links keep redirecting), a blocked destination fails with destination_blocked, and a custom slug needs Starter or above. If your workspace reaches its hourly link-creation limit, the job shows paused with a notice and resume_at and continues by itself. Jobs and their results are kept for 30 days after they finish.