Skip to content
Origami API

The production line, programmable

Everything the workspace does — upload, evaluate, improve, download — driven from your own systems over a simple JSON API.

The loop

The API mirrors the workspace: four steps, repeated per book.

01

Upload

Declare the file, PUT the bytes to a presigned URL, register the publication. Files never route through the API itself.

02

Run

Start any tool against the publication's working version. The response is a run you poll — sync tools finish on the first poll.

03

Read

Fetch the run's JSON report: findings, scores, metadata, or the publication-page description.

04

Download

Repairs and edits append new file versions. Download the working version via a short-lived link.

Authentication

Every request carries a workspace API key as a Bearer token. The key is bound to one workspace: everything you create and read through it lives there, exactly as if you were working in the app.

Keys are issued per workspace and shown once. Self-serve key management is coming to workspace settings; until then, request a key from your publica.la contact.

curl https://origami.publica.la/api/v1/publications \
  -H "Authorization: Bearer ${ORIGAMI_API_KEY}" \
  -H "Accept: application/json"

Quickstart

Six requests take a book from your disk to a validation report and back. Replace the token and file name; everything else is copy-paste.

1 · Ask for an upload slot

curl -X POST https://origami.publica.la/api/v1/uploads \
  -H "Authorization: Bearer ${ORIGAMI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"original_filename": "book.epub", "size_bytes": 4180294}'

2 · PUT the bytes to the presigned URL

curl -X PUT "UPLOAD_URL_FROM_STEP_1" \
  -H "Content-Type: application/epub+zip" \
  --data-binary @book.epub

3 · Register the publication

curl -X POST https://origami.publica.la/api/v1/publications \
  -H "Authorization: Bearer ${ORIGAMI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"publication_id": "ID_FROM_STEP_1", "key": "KEY_FROM_STEP_1", "original_filename": "book.epub", "size_bytes": 4180294}'

4 · Run a tool against it

curl -X POST https://origami.publica.la/api/v1/publications/PUBLICATION_ID/runs \
  -H "Authorization: Bearer ${ORIGAMI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"tool": "epub-check"}'

5 · Poll the run, then read the report

curl https://origami.publica.la/api/v1/runs/RUN_ID \
  -H "Authorization: Bearer ${ORIGAMI_API_KEY}"

curl https://origami.publica.la/api/v1/runs/RUN_ID/report \
  -H "Authorization: Bearer ${ORIGAMI_API_KEY}"

6 · Download the working version

curl https://origami.publica.la/api/v1/publications/PUBLICATION_ID/files/current \
  -H "Authorization: Bearer ${ORIGAMI_API_KEY}"

curl -L -o book-improved.epub \
  https://origami.publica.la/api/v1/files/FILE_ID/download \
  -H "Authorization: Bearer ${ORIGAMI_API_KEY}"

Endpoints

All endpoints live under /api/v1, speak JSON, and answer errors as {error, reason, detail} with a stable machine reason.

Publications & uploads

GET /api/v1/tools

The tool catalog as the API exposes it, with metering flags.

POST /api/v1/uploads

Mint a presigned PUT for a new file (30 minutes).

POST /api/v1/publications

Register an uploaded object as a publication.

GET /api/v1/publications

List the workspace's publications (cursor pagination).

GET /api/v1/publications/{id}

One publication: type, status, title, working file.

File versions

GET /api/v1/publications/{id}/files

The full version history: the immutable original plus every improved copy.

GET /api/v1/publications/{id}/files/current

The working version — what the next tool run acts on.

GET /api/v1/files/{id}/download

302 to a short-lived download link for any version.

Tool runs

POST /api/v1/publications/{id}/runs

Start a tool run (202). Accepts an options object and an Idempotency-Key header.

GET /api/v1/publications/{id}/runs

List a publication's runs, filterable by tool.

GET /api/v1/runs/{id}

Run status, timing and error detail.

GET /api/v1/runs/{id}/report

The finished run's JSON report.

Conventions

Async by default

Runs answer 202 with a resource you poll. A run is terminal at succeeded, failed or rejected.

Idempotency

Send an Idempotency-Key header on POST /runs; a retry returns the original run instead of spending twice.

Pagination

Lists answer {data, next_cursor, has_more}; pass next_cursor back as ?cursor= until has_more is false.

Limits

Requests are throttled per key. Metered tools share your workspace's daily fair-use allowance — a 429 with reason daily_limit_reached means try again tomorrow, and uploads consume the plan's publication allowance.

Descriptions

The description tool returns the publication-page copy: one style (back_cover) with a long version for the page body and a short one for cards and metadata.

Files move directly

Uploads are presigned PUTs and downloads presigned GETs against storage — the API never proxies file bytes, so transfers are fast at any size.

Building an integration?

Tell us what you're automating — bulk ingestion, a DAM hook, a preflight pipeline — and we'll help you wire it.