Shiori

API Reference

Programmatic access to your Shiori links. Use the API to save, fetch, update, and delete links from your own scripts, apps, and integrations.

Base URL

https://www.shiori.sh

Authentication

All API requests require an API key sent as a Bearer token in the Authorization header.

Getting an API key

Open Settings in Shiori, find the API key section, and click Generate. Copy the key immediately — it won't be shown again.

Using the key

Include the key in every request:

curl https://www.shiori.sh/api/links \
  -H "Authorization: Bearer shk_your_api_key_here"

Rate Limiting

API requests are limited to 60 requests per minute per API key. Link creation is further limited to 30 per minute. When rate limited, the API returns 429 Too Many Requests with these headers:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed
X-RateLimit-RemainingRequests remaining in window
X-RateLimit-ResetUnix timestamp when window resets
Retry-AfterSeconds to wait before retrying

Response Format

All responses are JSON with a success boolean. On errors, an error string is included.

Success:

{
  "success": true,
  "links": [...],
  "total": 42
}

Error:

{
  "success": false,
  "error": "Invalid API key"
}

Endpoints

GET /api/links

Fetch a paginated list of your saved links.

Query parameters

ParameterTypeDefaultDescription
limitinteger50Number of links to return (max 100)
offsetinteger0Number of links to skip
readstringallFilter by read status: all, read, or unread
sortstringnewestSort order: newest or oldest
curl "https://www.shiori.sh/api/links?limit=10&read=unread" \
  -H "Authorization: Bearer shk_your_api_key_here"

Response:

{
  "success": true,
  "links": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "url": "https://example.com/article",
      "title": "Example Article",
      "domain": "example.com",
      "summary": "A brief AI-generated summary...",
      "favicon_url": null,
      "image_url": null,
      "status": "created",
      "source": "api",
      "created_at": "2026-02-21T12:00:00.000Z",
      "updated_at": "2026-02-21T12:00:00.000Z",
      "read_at": null,
      "hn_url": null
    }
  ],
  "total": 142
}

POST /api/links

Save a new link. The link is created immediately and processed in the background (metadata extraction, AI summary).

Request body (JSON)

FieldTypeRequiredDescription
urlstringYesThe URL to save
titlestringNoCustom title (auto-extracted if omitted)
readbooleanNoSave as already read (default: false)
curl -X POST https://www.shiori.sh/api/links \
  -H "Authorization: Bearer shk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/article"}'

Response:

{
  "success": true,
  "linkId": "550e8400-e29b-41d4-a716-446655440000"
}

If the URL was already saved, the response includes duplicate: true and the existing link is bumped to the top of your inbox.


PATCH /api/links

Mark one or more links as read or unread in a single request.

Request body (JSON)

FieldTypeRequiredDescription
idsstring[]YesArray of link IDs to update
readbooleanYestrue to archive, false to move back to inbox
curl -X PATCH https://www.shiori.sh/api/links \
  -H "Authorization: Bearer shk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["550e8400-e29b-41d4-a716-446655440000"], "read": true}'

Response:

{
  "success": true,
  "updated": 1
}

PATCH /api/links/:id

Update a single link. Supports two operations: toggling read status and editing the title/summary.

Toggle read status

FieldTypeRequiredDescription
readbooleanYestrue to archive, false to move back to inbox
curl -X PATCH https://www.shiori.sh/api/links/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer shk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"read": true}'

Edit title & summary

FieldTypeRequiredDescription
titlestringYesNew title (1–500 characters)
summarystring or nullNoNew summary (max 2000 characters), null to clear
curl -X PATCH https://www.shiori.sh/api/links/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer shk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"title": "Updated Title", "summary": "New summary text"}'

Response:

{
  "success": true,
  "message": "Link updated",
  "linkId": "550e8400-e29b-41d4-a716-446655440000"
}

Returns 409 if the link is still being processed.


DELETE /api/links/:id

Move a link to the trash. Trashed links are automatically and permanently deleted after 7 days.

curl -X DELETE https://www.shiori.sh/api/links/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer shk_your_api_key_here"

Response:

{
  "success": true,
  "message": "Link deleted successfully",
  "linkId": "550e8400-e29b-41d4-a716-446655440000"
}

PATCH /api/links/:id — Restore from trash

Restore a previously deleted link from the trash.

curl -X PATCH https://www.shiori.sh/api/links/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer shk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"restore": true}'

Response:

{
  "success": true,
  "message": "Link restored",
  "linkId": "550e8400-e29b-41d4-a716-446655440000"
}

GET /api/links?trash=true

Fetch links that are in the trash. Supports the same limit and offset parameters as the regular list endpoint.

curl "https://www.shiori.sh/api/links?trash=true&limit=10" \
  -H "Authorization: Bearer shk_your_api_key_here"

DELETE /api/links

Permanently delete all links in the trash. This cannot be undone.

curl -X DELETE https://www.shiori.sh/api/links \
  -H "Authorization: Bearer shk_your_api_key_here"

Response:

{
  "success": true,
  "deleted": 12
}

Error Codes

StatusDescription
400Bad request — missing or invalid parameters
401Unauthorized — missing or invalid API key
404Not found — link does not exist or not yours
409Conflict — link is still being processed
429Rate limited — too many requests
500Server error