Programmatic access to your Shiori links and subscriptions. Use the API to save, fetch, update, and delete links, and manage RSS subscriptions from your own scripts, apps, and integrations.
https://www.shiori.sh
All API requests require an API key sent as a Bearer token in the Authorization header.
Open Settings in Shiori, find the API key section, and click Generate. Copy the key immediately — it won't be shown again.
Include the key in every request:
curl https://www.shiori.sh/api/links \
-H "Authorization: Bearer shk_your_api_key_here"
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:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed |
| X-RateLimit-Remaining | Requests remaining in window |
| X-RateLimit-Reset | Unix timestamp when window resets |
| Retry-After | Seconds to wait before retrying |
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"
}
Fetch a paginated list of your saved links.
| Parameter | Type | Default | Description |
|---|---|---|---|
| limit | integer | 25 | Number of links to return (max 1000) |
| offset | integer | 0 | Number of links to skip |
| read | string | all | Filter by read status: all, read, or unread |
| sort | string | newest | Sort order: newest or oldest |
| search | string | Full-text search across title, summary, and content | |
| tag | string | Filter by tag name or tag ID | |
| since | string | ISO 8601 timestamp — only return links created at or after this time | |
| include_content | boolean | false | Include full markdown content in each link object |
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 of the article.",
"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,
"deleted_at": null,
"purged_at": null,
"hn_url": null,
"file_type": null,
"file_mime_type": null,
"notion_page_id": null,
"author": null,
"discoverable_feed_url": null
}
],
"total": 142
}
Save a new link. The link is created immediately and processed in the background (metadata extraction, AI summary).
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The URL to save |
| title | string | No | Custom title (auto-extracted if omitted) |
| read | boolean | No | Save as already read (default: false) |
| created_at | string | No | ISO 8601 datetime to override the saved date (useful for backfilling) |
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.
Bulk update links. Supports two operations: toggling read status and moving to trash.
| Field | Type | Required | Description |
|---|---|---|---|
| ids | string[] | Yes | Array of link IDs to update |
| read | boolean | Yes | true 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}'
| Field | Type | Required | Description |
|---|---|---|---|
| ids | string[] | Yes | Array of link IDs to trash |
| deleted | boolean | Yes | Must be true |
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"], "deleted": true}'
Response (both operations):
{
"success": true,
"updated": 1
}
Update a single link. Supports toggling read status, editing the title/summary, and overriding the saved date.
| Field | Type | Required | Description |
|---|---|---|---|
| read | boolean | Yes | true 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}'
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | New title (1–500 characters) |
| summary | string or null | No | New summary (max 2000 characters), null to clear |
| created_at | string | No | ISO 8601 datetime to override the saved date |
You can also update created_at on its own without providing title:
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 '{"created_at": "2024-01-15T12:00:00Z"}'
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.
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"
}
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"
}
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"
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
}
List your RSS subscriptions.
curl https://www.shiori.sh/api/subscriptions/ \
-H "Authorization: Bearer shk_your_api_key_here"
Response:
{
"success": true,
"subscriptions": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"feed_url": "https://example.com/feed.xml",
"title": "Example Blog",
"description": "A great blog",
"site_url": "https://example.com",
"icon_url": "https://icons.tango.us/example.com",
"last_synced_at": "2026-03-07T12:00:00Z"
}
]
}
Subscribe to an RSS or Atom feed. Accepts a website URL or direct feed URL — the feed is auto-discovered.
| Field | Type | Required | Description |
|---|---|---|---|
| feedUrl | string | Yes | URL of the feed or website |
| initialSync | boolean | No | Sync the 3 most recent items (default: false) |
curl -X POST https://www.shiori.sh/api/subscriptions/ \
-H "Authorization: Bearer shk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"feedUrl": "https://example.com/feed.xml", "initialSync": true}'
Response:
{
"success": true,
"subscription": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"feed_url": "https://example.com/feed.xml",
"title": "Example Blog"
}
}
Returns 409 if you are already subscribed to this feed.
Remove a subscription.
curl -X DELETE https://www.shiori.sh/api/subscriptions/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer shk_your_api_key_here"
Response:
{
"success": true,
"deleted": true
}
Trigger an immediate sync for a subscription. New feed items are saved as links.
| Field | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Max items to sync (1–100) |
curl -X POST https://www.shiori.sh/api/subscriptions/sync/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer shk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"limit": 5}'
Response:
{
"success": true,
"subscriptionId": "550e8400-e29b-41d4-a716-446655440000",
"newItems": 3,
"skipped": 2,
"errors": 0,
"syncedAt": "2026-03-07T12:00:00Z"
}
List all your tags, ordered by position.
curl https://www.shiori.sh/api/tags \
-H "Authorization: Bearer shk_your_api_key_here"
Response:
{
"success": true,
"tags": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "design",
"position": 0,
"created_at": "2026-03-10T12:00:00Z"
}
]
}
Create a new tag. Names are automatically slugified (lowercased, spaces replaced with hyphens, max 16 characters).
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Tag name |
curl -X POST https://www.shiori.sh/api/tags \
-H "Authorization: Bearer shk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"name": "design"}'
Response:
{
"success": true,
"tag": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "design",
"position": 0,
"created_at": "2026-03-10T12:00:00Z"
}
}
Returns 409 if a tag with that name already exists.
Rename a tag.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | New tag name |
curl -X PATCH https://www.shiori.sh/api/tags/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer shk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"name": "engineering"}'
Response:
{
"success": true,
"tag": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "engineering",
"position": 0,
"created_at": "2026-03-10T12:00:00Z"
}
}
Delete a tag. Links are untagged but not deleted.
curl -X DELETE https://www.shiori.sh/api/tags/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer shk_your_api_key_here"
Response:
{
"success": true,
"deleted": true
}
Set the tags on a link. Replaces all existing tags with the provided list.
| Field | Type | Required | Description |
|---|---|---|---|
| tagIds | string[] | Yes | Array of tag IDs (max 10 per link) |
curl -X PUT https://www.shiori.sh/api/links/550e8400-e29b-41d4-a716-446655440000/tags \
-H "Authorization: Bearer shk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"tagIds": ["tag-id-1", "tag-id-2"]}'
Response:
{
"success": true
}
Get the authenticated user's profile and subscription info.
curl https://www.shiori.sh/api/user/me \
-H "Authorization: Bearer shk_your_api_key_here"
Response:
{
"success": true,
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"full_name": "Jane Doe",
"avatar_url": "https://example.com/avatar.jpg",
"created_at": "2025-01-15T12:00:00Z",
"subscription": {
"plan": "subscription",
"is_active": true,
"status": "active"
}
}
}
| Status | Description |
|---|---|
| 400 | Bad request — missing or invalid parameters |
| 401 | Unauthorized — missing or invalid API key |
| 404 | Not found — link does not exist or not yours |
| 409 | Conflict — link is still being processed |
| 429 | Rate limited — too many requests |
| 500 | Server error |