Categories

Endpoints to list, create, and delete categories in Paperarchive. Categories are user-owned and assigned to spaces via the category_spaces model.

GET https://api.paperarchive.io/v1/categories
Scope:categories:read

List categories you own that are linked to any accessible space (legacy categories.space_id or rows in category_spaces). Each item includes membership_space_ids for all linked spaces.

Code examples

curl -X GET "https://api.paperarchive.io/v1/categories" \
  -H "Authorization: Bearer pa_live_abc123def456"
POST https://api.paperarchive.io/v1/categories
Scope:categories:write

Create a category and assign it to a space. If space_id is omitted, your default space is used (when it exists). Paperarchive checks the name against your existing categories first: when a top-level category with the same name (ignoring case and surrounding spaces) exists, it is returned with status 200 instead of creating a duplicate. When similar categories exist (other spelling such as "&" vs "and", singular/plural, synonyms like "Car"/"Vehicle", or names contained in each other), the request fails with 409 and error "similar_exists" plus the candidates; send force: true to create the category anyway. A new category returns 201.

Request body

NameTypeRequiredDescription
namestring required Category name.
space_iduuid optional Target space for the first membership. Omit to use your default space.
colorstring optional Hex color code (e.g. "#ef4444").
iconstring optional Icon name.
forceboolean optional Create the category even when similar categories exist (skips the 409 similar_exists answer). An exact name still returns the existing category.

Code examples

curl -X POST "https://api.paperarchive.io/v1/categories" \
  -H "Authorization: Bearer pa_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{"name": "Receipts", "space_id": "space-uuid-1", "color": "#f59e0b"}'
DELETE https://api.paperarchive.io/v1/categories/:id
Scope:categories:write

Move a category you created to the trash (soft delete) when it is linked to at least one space your key can access (category_spaces or legacy space_id). Only the creator can delete a category; it can be restored in the app for 30 days, and its documents keep their assignment.

Path parameters

NameTypeRequiredDescription
iduuid required The category ID to delete.

Code examples

curl -X DELETE "https://api.paperarchive.io/v1/categories/cat-uuid-1" \
  -H "Authorization: Bearer pa_live_abc123def456"

Smoke test checklist (categories API)

Use a test API key with categories:read and categories:write (and spaces:read so you can resolve space UUIDs). Run against staging or local API.

  1. GET /v1/categories - Expect 200, success: true, array data. Each item has membership_space_ids (array, possibly empty for legacy rows before backfill).
  2. POST with explicit space_id - POST /v1/categories with body {"name":"API Smoke Cat","space_id":"<uuid>"}. Expect 201, returned membership_space_ids contains that space.
  3. POST without space_id - Same with only {"name":"API Smoke Cat Default"}. Expect 201 if a default space exists, or 400 with a clear error if not.
  4. GET again - New category appears; membership_space_ids matches the space you used (or default).
  5. POST the same name again - Expect 200 and the same id (no duplicate).
  6. POST a similar name - e.g. the plural of the name. Expect 409 with error: "similar_exists" and candidates; with "force": true expect 201.
  7. DELETE - DELETE /v1/categories/<id> with the new id. Expect 200 and success: true. Repeat GET to confirm it is gone (it is in the trash).
  8. Restricted API key - With a key limited to one space, repeat POST targeting a space outside the key: expect 403.