Download OpenAPI specification:
API documentation for the Hebban.nl project.
See the changelog for the full API history.
Every API request must include:
Accept: application/json — Without this header, you'll receive 406 Not Acceptable.X-API-TOKEN: <your-token> — All endpoints require a valid API token (see Authentication below).The API uses two authentication schemes:
X-API-TOKEN header) — Required for all requests. Identifies your application./me/*). Obtained via /auth/login or /auth/register.Token lifecycle:
/auth/logout./auth/refresh to extend token lifetime if needed (rarely necessary).Common pitfalls:
X-API-TOKEN header → 401 Unauthenticated/me/* endpoints → 401 Unauthenticated/auth/logout when user signs out → Tokens remain validTrack requests across logs and errors using the X-Request-Id header:
400 Bad Request.X-Request-Id in the header.X-Request-Id header and the request_id field in the JSON body.All errors follow the RFC 9457 Problem Details format with Content-Type: application/problem+json:
{
"title": "Unauthenticated",
"status": 401,
"request_id": "01JCEXAMPLE123456789ABCDEF",
"code": "auth.unauthenticated"
}
Common error codes:
400 Bad Request — Invalid request format or parameters401 Unauthenticated — Missing or invalid authentication403 Forbidden — Authenticated but not authorized404 Not Found — Resource doesn't exist406 Not Acceptable — Missing Accept: application/json header422 Unprocessable Content — Validation errors (includes errors field with details)429 Too Many Requests — Rate limit exceededAll API endpoints are rate limited. Limits are applied per consumer and are indicated via response headers:
X-RateLimit-Limit — Maximum requests allowed in the current windowX-RateLimit-Remaining — Requests remaining in the current windowThree tiers apply:
/*/search endpoints have a stricter limit (default: 30 requests/minute)/me/collections, /me/activity, /me/app-sync (default: 20 requests/minute)When a limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header.
List endpoints support pagination via query parameters:
page — Page number (default: 1)per_page — Items per page (default: 15, max: 250)Some endpoints use cursor-based pagination (e.g., /me/notifications) with a before timestamp parameter.
Some endpoints are idempotent and safe to retry:
204 No Content even if the resource was already deleted.204 No Content if the work is already present.This prevents errors when retrying failed requests or handling network issues.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| email required | string <email> |
| password required | string <password> |
{- "email": "user@example.com",
- "password": "pa$$word"
}{- "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
- "token_type": "Bearer",
- "expires_in": 315360000,
- "user": {
- "id": 0,
- "name": "string",
- "slug": "string",
- "email": "string",
- "user_label": "normal",
- "avatar": { },
- "email_verified_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| name required | string |
| email required | string <email> |
| password required | string <password> |
| password_confirmation required | string <password> |
{- "name": "string",
- "email": "user@example.com",
- "password": "pa$$word",
- "password_confirmation": "pa$$word"
}{- "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
- "token_type": "Bearer",
- "expires_in": 315360000,
- "user": {
- "id": 0,
- "name": "string",
- "slug": "string",
- "email": "string",
- "user_label": "normal",
- "avatar": { },
- "email_verified_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Begins the in-app registration flow by sending a one-time verification code to the email address. The response is identical whether the address is new or already registered (anti-enumeration); an already-registered address instead receives a "you already have an account" email with a password-reset link. No account is created at this step.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| email required | string <email> |
{- "email": "user@example.com"
}{- "message": "string"
}Re-sends a fresh verification code, invalidating any previous one. The response is identical regardless of whether the address is already registered (anti-enumeration).
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| email required | string <email> |
{- "email": "user@example.com"
}{- "message": "string"
}Verifies the one-time code. On success returns a short-lived, single-use proof bound to the email, to be submitted at the completion step. The code is limited-use and locks out after too many incorrect attempts.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| email required | string <email> |
| code required | string The one-time verification code sent to the email address. |
{- "email": "user@example.com",
- "code": "string"
}{- "proof": "string",
- "expires_at": "2030-01-01T00:00:00+00:00"
}Validates any subset of the registration fields against the exact rules applied at completion, for live per-field feedback. Stores nothing. Password strength is checked without requiring confirmation.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| password | string <password> |
| password_confirmation | string <password> |
| name | string |
| birthdate | string <date> |
{- "password": "pa$$word",
- "password_confirmation": "pa$$word",
- "name": "string",
- "birthdate": "2019-08-24"
}{- "valid": true,
- "fields": [
- "password",
- "name"
]
}Creates a complete, already-verified account in one step from the proof returned by verify-code. The email is taken from the proof, not the request body. Returns a JWT, like login; no verification-link email is sent. If the email was registered in the meantime, returns 409.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| proof required | string The short-lived confirmation proof returned by verify-code. The email is derived from it. |
| password required | string <password> |
| password_confirmation required | string <password> |
| name required | string |
| birthdate | string <date> |
| terms required | boolean Acceptance of the terms and conditions. Must be true. Value: true |
{- "proof": "string",
- "password": "pa$$word",
- "password_confirmation": "pa$$word",
- "name": "string",
- "birthdate": "2019-08-24",
- "terms": true
}{- "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
- "token_type": "Bearer",
- "expires_in": 315360000,
- "user": {
- "id": 0,
- "name": "string",
- "slug": "string",
- "email": "string",
- "user_label": "normal",
- "avatar": { },
- "email_verified_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Requests a password reset link for an email address.
This endpoint never reveals whether an account exists. A registered
address, an unknown address, and an address that already requested a link
moments ago all return the exact same 200 response. Only the submitted
value is validated: a missing or syntactically invalid email still returns
422.
Consequences for clients:
200 as confirmation that an account was found.The endpoint is rate limited per email address, per IP, and by an overall
ceiling; exceeding any of these returns 429.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| email required | string <email> |
{- "email": "user@example.com"
}{- "status": "We have emailed your password reset link."
}Validates a password reset token without consuming it. Use this before showing the reset form to provide immediate feedback if the link has expired or is invalid.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| email required | string <email> |
| token required | string |
{- "email": "user@example.com",
- "token": "string"
}{- "valid": true
}| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| email required | string <email> |
| token required | string |
| password required | string <password> |
| password_confirmation required | string <password> |
{- "email": "user@example.com",
- "token": "string",
- "password": "pa$$word",
- "password_confirmation": "pa$$word"
}{- "message": "string"
}Verifies a user's email address using a signed URL. No authentication required - the signed URL itself is proof of email ownership.
| id required | integer |
| hash required | string |
| expires required | integer URL expiration timestamp |
| signature required | string Cryptographic signature for URL validation |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "message": "string"
}Resend the email verification link to the authenticated user. Rate limited to 3 requests per hour.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "message": "Verification email sent."
}| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
- "token_type": "Bearer",
- "expires_in": 315360000,
- "user": {
- "id": 0,
- "name": "string",
- "slug": "string",
- "email": "string",
- "user_label": "normal",
- "avatar": { },
- "email_verified_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Returns the authenticated user's own profile with private fields.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 88,
- "slug": "marty-mcfly",
- "name": "Marty McFly",
- "email": "marty@hillvalleymusic.com",
- "email_verified_at": "1955-11-12T06:00:00+00:00",
- "user_label": "normal",
- "last_activity_at": "1985-10-26T08:18:00+00:00",
- "biography": "If you put your mind to it, you can accomplish anything.",
- "profile_visibility": "public",
- "birthdate": "1968-06-12",
- "gender": "male",
- "followers_count": 256,
- "following_count": 42,
- "reviews_count": 75,
- "challenges_count": 3,
- "reading_status_want_to_read_count": 34,
- "reading_status_read_count": 128,
- "reading_status_reading_count": 5,
- "created_at": "1955-11-12T06:00:00+00:00",
- "updated_at": "1985-10-26T08:18:00+00:00",
- "preferences": {
- "ui": {
- "theme": "retro",
- "sidebar_collapsed": false
}, - "profile": {
- "show_birthdate": true,
- "show_gender": true
}, - "notifications": {
- "comment.on.review": true,
- "follow": true
}
}
}
}Partially update the authenticated user's profile (PATCH semantics). Only provided fields will be updated.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| name | string <= 255 characters User's display name |
string <email> <= 255 characters User's email address (must be unique) | |
| password | string <password> >= 8 characters New password (requires password_confirmation) |
| password_confirmation | string <password> >= 8 characters Password confirmation (required when password is provided) |
null or Gender (string) User's gender preference | |
null or string <= 15000 characters User's biography or about text | |
null or string User's birthdate in YYYY-MM-DD format (cannot be in the future) | |
| profile_visibility | string (ProfileVisibility) Enum: "public" "protected" "private" User's profile visibility setting. Protected = visible to authenticated users. |
{- "name": "Jane Doe",
- "email": "jane@example.com",
- "password": "new-secure-password",
- "password_confirmation": "new-secure-password",
- "gender": { },
- "biography": "I love reading books about history and science fiction.",
- "birthdate": "1990-05-15",
- "profile_visibility": "public"
}{- "data": {
- "id": 0,
- "slug": "string",
- "name": "string",
- "user_label": "normal",
- "email": "user@example.com",
- "email_verified_at": { },
- "avatar": { },
- "biography": { },
- "birthdate": { },
- "gender": { },
- "profile_visibility": "public",
- "followers_count": 0,
- "following_count": 0,
- "reviews_count": 0,
- "challenges_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "last_activity_at": "2019-08-24T14:15:22Z",
- "preferences": {
- "ui": {
- "theme": "dark",
- "sidebar_collapsed": false
}, - "profile": {
- "show_birthdate": false,
- "show_gender": false
}, - "notifications": {
- "comment.on.review": true,
- "follow": false,
- "like.on.comment": true
}
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Permanently deletes the authenticated user's account. The account is locked out immediately; data cleanup happens asynchronously.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Upload a new avatar image for the authenticated user. If an avatar already exists, it will be replaced and the old file deleted.
Important: This endpoint requires multipart/form-data content type. Sending the file as a JSON string or base64-encoded body will be rejected.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| avatar required | string <binary> Avatar image file (JPEG, PNG, or WebP, max 2048 KB / 2 MB) |
{- "data": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}
}Remove the current user's avatar image
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}
}Update user preferences for the authenticated user. Supports 'ui' and 'notifications' namespaces. Values are merged with existing preferences (not replaced).
You can update one or both namespaces in a single request.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
object <= 50 properties Client-side UI preferences. No key validation - clients can store any valid JSON structure (max 50 keys). | |
object Profile visibility preferences. Only | |
object Notification preferences. All properties are optional boolean values for each NotificationType. |
{- "ui": {
- "theme": "dark",
- "sidebar_collapsed": false
}, - "profile": {
- "show_birthdate": true,
- "show_gender": true
}, - "notifications": {
- "comment.on.review": false,
- "comment.on.comment": true,
- "like.on.review": true,
- "like.on.comment": false,
- "like.on.book_list": true,
- "follow": true,
- "followed_user.reviews": false,
- "followed_user.rates": true,
- "followed_user.reading_status": false
}
}{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "email_verified_at": { },
- "name": "string",
- "avatar": { },
- "last_activity_at": "2019-08-24T14:15:22Z",
- "unread_notifications_count": 0
}
}| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "read": [
- 101,
- 102
], - "reading": [ ],
- "to_read": [
- 203
], - "reviewed": [
- [
- 203,
- 5011
]
], - "favorites": [
- 101,
- 203,
- 304
], - "rating": [
- [
- 101,
- 4
], - [
- 203,
- 5
]
], - "campaign_submitted": [ ],
- "like": {
- "article": [
- 123,
- 1212
], - "review": [
- 456
], - "booklist": [
- 789,
- 7878
], - "comment": [
- 1011
], - "event": [
- 1212,
- 1211
]
}, - "follow": {
- "author": [ ],
- "user": [ ]
}
}
}Returns user activity data with timestamps for app synchronization.
Unlike /me/activity, this endpoint includes timestamps on all fields,
making it suitable for syncing user state after login.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "read": [
- {
- "work_id": 101,
- "finished_on": [
- "2024-03-15"
], - "created_at": "2024-03-15T10:30:00+00:00",
- "updated_at": "2024-03-15T10:30:00+00:00"
}, - {
- "work_id": 102,
- "finished_on": [
- "2024-01-20"
], - "created_at": "2024-01-20T14:00:00+00:00",
- "updated_at": "2024-01-20T14:00:00+00:00"
}
], - "reading": [
- {
- "work_id": 203,
- "created_at": "2024-03-10T09:15:00+00:00"
}
], - "to_read": [
- {
- "work_id": 304,
- "created_at": "2024-02-01T11:00:00+00:00"
}
], - "favorites": [
- {
- "work_id": 101,
- "created_at": "2024-01-15T08:30:00+00:00"
}
], - "owned": [
- {
- "work_id": 102,
- "created_at": "2024-01-18T09:45:00+00:00"
}
], - "rating": [
- {
- "work_id": 101,
- "stars": 4,
- "created_at": "2024-03-16T12:00:00+00:00"
}
], - "reviewed": [
- {
- "work_id": 101,
- "review_id": 5011,
- "created_at": "2024-03-17T15:30:00+00:00"
}
]
}
}Returns a paginated list of the authenticated user's notifications. Supports filtering by read status and cursor-based pagination.
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| unread | integer Enum: 0 1 Filter to only unread notifications. Use |
| before | string <date-time> Return notifications created before this timestamp (RFC 3339 format) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "comment.on.review",
- "data": {
- "v": 1,
- "type": "like.on.review",
- "actor": {
- "id": 0,
- "name": "string",
- "slug": "string",
- "avatar": { }
}, - "subject": {
- "type": "review",
- "id": 0
}, - "context": {
- "parent": {
- "type": "review",
- "review": {
- "id": 0,
- "slug": "string",
- "title": "string",
- "stars": 1,
- "description": "string"
}, - "work": {
- "id": 0,
- "slug": "string",
- "title": "string",
- "cover_url": { },
- "description": { },
- "authors": [
- {
- "id": 0,
- "name": "string",
- "slug": "string"
}
]
}
}
}, - "meta": { }
}, - "read_at": { },
- "created_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Marks multiple notifications as read for the authenticated user. Can mark specific notifications by ID or all notifications (optionally filtered to unread only).
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| all required | boolean Mark all notifications as read |
| unread_only | boolean When 'all' is true, only mark unread notifications |
{- "ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes multiple notifications by ID for the authenticated user.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| ids required | Array of strings <uuid> non-empty [ items <uuid > ] Notification IDs to delete |
{- "ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Idempotently marks a specific notification as read for the authenticated user. Returns 204 even if the notification doesn't exist, doesn't belong to the user, or is already read.
| id required | string <uuid> Notification ID (UUID) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Idempotently deletes a specific notification for the authenticated user. Returns 204 even if the notification doesn't exist or doesn't belong to the user.
| id required | string <uuid> Notification ID (UUID) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Returns the count of unread notifications for the authenticated user.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "count": 0
}Returns all notification mutes for the authenticated user.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "subject_type": "string",
- "subject_id": 0,
- "type": { },
- "until": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Creates or updates a notification mute for the authenticated user. If a mute already exists for the same subject_type, subject_id, and type combination, it will be updated.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| subject_type required | string Fully qualified class name of the subject to mute |
| subject_id required | integer ID of the subject to mute |
null or string Specific notification type to mute (null to mute all types for this subject) | |
null or string When the mute should expire (null for indefinite, RFC 3339 format) |
{- "subject_type": "string",
- "subject_id": 0,
- "type": { },
- "until": { }
}{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes a notification mute for the authenticated user. Idempotent - returns 204 even if the mute doesn't exist.
| id required | integer The ID of the notification mute to delete |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Lists users and contributors (authors) the authenticated user follows.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "authors": [
- {
- "id": 456,
- "name": "J.K. Rowling",
- "slug": "jk-rowling",
- "portrait_url": { },
- "portrait_alt_text": { },
- "portrait_attribution": { },
- "followed_at": "2025-01-15T10:30:00+00:00"
}
], - "users": [
- {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00",
- "followed_at": "2025-01-15T10:30:00+00:00"
}
]
}
}Lists users who follow the authenticated user (paginated).
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00",
- "followed_at": "2025-01-15T10:30:00+00:00"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Exchanges a one-time assume token (generated by the CMS) for a short-lived
impersonation JWT. The assume token is consumed atomically — it cannot be
reused. The resulting JWT carries act and impersonation claims for
audit traceability.
No Bearer token required — the assume token itself is the credential.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| token required | string = 64 characters The 64-character hex-encoded assume token |
{- "token": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
}{- "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
- "token_type": "Bearer",
- "expires_in": 315360000,
- "user": {
- "id": 0,
- "name": "string",
- "slug": "string",
- "email": "string",
- "user_label": "normal",
- "avatar": { },
- "email_verified_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Blacklists the current impersonation JWT, ending the impersonation session.
Only works with tokens that carry the impersonation claim.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Search for users with support for sorting and pagination
| page | integer >= 1 Default: 1 The page number for traditional pagination (used by search endpoints) |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| query required | string [ 2 .. 255 ] characters Search query (minimum 2 characters) |
| sort_by | string Default: "relevance" Enum: "relevance" "name" "followers_count" Field to sort results by. When |
| sort_direction | string (SortDirection) Default: "asc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}
], - "links": {
}, - "meta": {
- "current_page": 0,
- "from": 0,
- "last_page": 0,
- "per_page": 0,
- "to": 0,
- "total": 0
}
}Gets a paginated list of users.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a user profile by ID. Includes profile fields (biography, birthdate, gender) and visibility preferences. Email is never exposed in this endpoint.
| user_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "name": "string",
- "slug": "string",
- "user_label": "normal",
- "avatar": { },
- "biography": { },
- "birthdate": { },
- "gender": { },
- "profile_visibility": "public",
- "followers_count": 0,
- "following_count": 0,
- "reviews_count": 0,
- "challenges_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "email_verified_at": { },
- "last_activity_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "preferences": {
- "profile": {
- "show_birthdate": true,
- "show_gender": true
}
}
}
}| slug required | string The unique username/slug of the user |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "name": "string",
- "slug": "string",
- "user_label": "normal",
- "avatar": { },
- "biography": { },
- "birthdate": { },
- "gender": { },
- "profile_visibility": "public",
- "followers_count": 0,
- "following_count": 0,
- "reviews_count": 0,
- "challenges_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "email_verified_at": { },
- "last_activity_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "preferences": {
- "profile": {
- "show_birthdate": true,
- "show_gender": true
}
}
}
}Used for redirecting old Hebban v1 URLs that use original username format (e.g., 'Hans Ramstijn-4759')
| legacySlug required | string The original username from Hebban v1 |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "name": "string",
- "slug": "string",
- "user_label": "normal",
- "avatar": { },
- "biography": { },
- "birthdate": { },
- "gender": { },
- "profile_visibility": "public",
- "followers_count": 0,
- "following_count": 0,
- "reviews_count": 0,
- "challenges_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "email_verified_at": { },
- "last_activity_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "preferences": {
- "profile": {
- "show_birthdate": true,
- "show_gender": true
}
}
}
}Lists users and contributors (authors) the specified user follows.
| user_id required | integer User ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "authors": [
- {
- "id": 456,
- "name": "J.K. Rowling",
- "slug": "jk-rowling",
- "portrait_url": { },
- "portrait_alt_text": { },
- "portrait_attribution": { },
- "followed_at": "2025-01-15T10:30:00+00:00"
}
], - "users": [
- {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00",
- "followed_at": "2025-01-15T10:30:00+00:00"
}
]
}
}Lists users who follow the specified user (paginated).
| user_id required | integer User ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00",
- "followed_at": "2025-01-15T10:30:00+00:00"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Lists users who follow the specified contributor (paginated).
| contributor_id required | integer Contributor ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00",
- "followed_at": "2025-01-15T10:30:00+00:00"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Idempotently follows the specified user (singleton per follower/followable). Requires authentication.
| user_id required | integer User ID to follow |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes the current user's follow for the specified user (idempotent). Requires authentication. Returns 204 even if there is no follow to delete.
| user_id required | integer User ID to unfollow |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Idempotently follows the specified contributor (singleton per follower/followable). Requires authentication.
| contributor_id required | integer Contributor ID to follow |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes the current user's follow for the specified contributor (idempotent). Requires authentication. Returns 204 even if there is no follow to delete.
| contributor_id required | integer Contributor ID to unfollow |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Lists comments for the review (default is nested with embedded children).
| review_id required | integer Review ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 1000 ] Default: 1000 The number of items per page (comments listing only). |
| nested | integer Default: 1 Enum: 0 1 When true (1, default), returns top-level comments with embedded children. When false (0), returns a flat list of all comments (parents and replies) without embedded children. |
| sort_by | string Default: "created_at" Value: "created_at" Field to sort comments by |
| sort_direction | string Default: "asc" Enum: "asc" "desc" Sort direction (asc = oldest-first, desc = newest-first) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "body": "string",
- "parent_id": 0,
- "likes_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "children": [
- { }
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Creates a comment for the review. Requires authentication.
| review_id required | integer Review ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| body required | string Comment text body |
| parent_id | integer or null Optional parent comment ID (single-level threading) |
{- "body": "string",
- "parent_id": 0
}{- "data": {
- "id": 0,
- "body": "string",
- "parent_id": 0,
- "likes_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "children": [
- { }
]
}
}Lists comments for the article (default is nested with embedded children)
| article_id required | integer Article ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 1000 ] Default: 1000 The number of items per page (comments listing only). |
| nested | integer Default: 1 Enum: 0 1 When true (1, default), returns top-level comments with embedded children. When false (0), returns a flat list of all comments (parents and replies) without embedded children. |
| sort_by | string Default: "created_at" Value: "created_at" Field to sort comments by |
| sort_direction | string Default: "asc" Enum: "asc" "desc" Sort direction (asc = oldest-first, desc = newest-first) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "body": "string",
- "parent_id": 0,
- "likes_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "children": [
- { }
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Creates a comment for the article. Requires authentication.
| article_id required | integer Article ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| body required | string Comment text body |
| parent_id | integer or null Optional parent comment ID (single-level threading) |
{- "body": "string",
- "parent_id": 0
}{- "data": {
- "id": 0,
- "body": "string",
- "parent_id": 0,
- "likes_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "children": [
- { }
]
}
}Lists comments for the campaign post (default is nested with embedded children). Book club post comments nest up to three levels deep (a reply to a reply to a top-level comment) — the children field recurses accordingly. Returns 404 if the post doesn't exist or isn't live (draft and scheduled posts are indistinguishable from posts that don't exist).
| campaign_post_id required | integer Campaign post ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 1000 ] Default: 1000 The number of items per page (comments listing only). |
| nested | integer Default: 1 Enum: 0 1 When true (1, default), returns top-level comments with embedded children. When false (0), returns a flat list of all comments (parents and replies) without embedded children. |
| sort_by | string Default: "created_at" Value: "created_at" Field to sort comments by |
| sort_direction | string Default: "asc" Enum: "asc" "desc" Sort direction (asc = oldest-first, desc = newest-first) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "body": "string",
- "parent_id": 0,
- "likes_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "children": [
- { }
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Creates a comment for the campaign post. Requires authentication, and the user must be an approved participant, coordinator, or editor of the post's book club.
When comments are closed for the post, this returns 422 for everyone — including coordinators and editors — because validation runs before authorization.
| campaign_post_id required | integer Campaign post ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| body required | string Comment text body |
| parent_id | integer or null Optional parent comment ID (up to three levels of nesting for book club posts) |
{- "body": "string",
- "parent_id": 0
}{- "data": {
- "id": 0,
- "body": "string",
- "parent_id": 0,
- "likes_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "children": [
- { }
]
}
}Lists comments for the event (default is nested with embedded children).
| event_id required | integer Event ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 1000 ] Default: 1000 The number of items per page (comments listing only). |
| nested | integer Default: 1 Enum: 0 1 When true (1, default), returns top-level comments with embedded children. When false (0), returns a flat list of all comments (parents and replies) without embedded children. |
| sort_by | string Default: "created_at" Value: "created_at" Field to sort comments by |
| sort_direction | string Default: "asc" Enum: "asc" "desc" Sort direction (asc = oldest-first, desc = newest-first) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "body": "string",
- "parent_id": 0,
- "likes_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "children": [
- { }
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Creates a comment for the event. Requires authentication.
| event_id required | integer Event ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| body required | string Comment text body |
| parent_id | integer or null Optional parent comment ID (single-level threading) |
{- "body": "string",
- "parent_id": 0
}{- "data": {
- "id": 0,
- "body": "string",
- "parent_id": 0,
- "likes_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "children": [
- { }
]
}
}Partially updates the comment body (PATCH semantics). Only the fields provided in the request body will be updated; not all comment fields need to be supplied. Requires authentication; only the author can update their own comment.
| comment_id required | integer Comment ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| body required | string New comment text body |
{- "body": "string"
}{- "data": {
- "id": 0,
- "body": "string",
- "parent_id": 0,
- "likes_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "children": [
- { }
]
}
}Deletes a comment. Requires authentication; only the author can delete their own comment.
| comment_id required | integer Comment ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Idempotently sets the current user's like for the review (singleton per user/review). Requires authentication.
| review_id required | integer Review ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes the current user's like for the review (idempotent). Requires authentication. Returns 204 even if there is no like to delete.
| review_id required | integer Review ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Idempotently sets the current user's like for the article (singleton per user/article). Requires authentication.
| article_id required | integer Article ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes the current user's like for the article (idempotent). Requires authentication. Returns 204 even if there is no like to delete.
| article_id required | integer Article ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Idempotently sets the current user's like for the list (singleton per user/list). Requires authentication.
| list_id required | integer List ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes the current user's like for the list (idempotent). Requires authentication. Returns 204 even if there is no like to delete.
| list_id required | integer List ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Idempotently sets the current user's like for the event (singleton per user/event). Requires authentication.
| event_id required | integer Event ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes the current user's like for the event (idempotent). Requires authentication. Returns 204 even if there is no like to delete.
| event_id required | integer Event ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Idempotently sets the current user's like for the comment (singleton per user/comment). Requires authentication.
| comment_id required | integer Comment ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes the current user's like for the comment (idempotent). Requires authentication. Returns 204 even if there is no like to delete.
| comment_id required | integer Comment ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Lists the authenticated user's reviews with pagination.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string",
- "editorial": false,
- "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "work": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Lists published reviews created by a specific user with pagination.
| user_id required | integer User ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string",
- "editorial": false,
- "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "work": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Lists published reviews with pagination.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| contributor_id | Array of integers <= 10 items [ items >= 1 ] Filter by contributor ID(s). Supports single or multiple contributors (OR logic). Examples:
Maximum 10 contributor IDs per request. |
| contributor_role | string^(?:A01|A12|A13|B01|B05|B06|C01|E07|Z98|Z99)$... Example: contributor_role=A01 Filter by ONIX contributor role. Based on ONIX codelist 17 (https://ns.editeur.org/onix/en/17). Codes: A01 (Author), A12 (Illustrator), A13 (Photographer), B01 (Editor), B05 (Adapter), B06 (Translator), C01 (Compiled by), E07 (Narrator), Z98 (Various), Z99 (Other). |
| user_id | integer >= 1 Filter records to those created by the given user ID. |
| work_id | integer >= 1 Filter records to those associated with the given work ID. |
| stars | integer [ 1 .. 5 ] Filter reviews to those with exactly this many stars (1-5). |
| min_stars | integer [ 1 .. 5 ] Filter reviews to those with stars greater than or equal to this value (1-5). |
| max_stars | integer [ 1 .. 5 ] Filter reviews to those with stars less than or equal to this value (1-5). |
| user_label[] | Array of strings [ 1 .. 3 ] items Items Enum: "normal" "team" "crew" Filter by the review author's user label (OR logic - reviews whose author has any of the specified labels). The frontend "Hebban" filter is user_label[]=team&user_label[]=crew. |
| genres[] | Array of integers [ 1 .. 10 ] items Filter by genre IDs (OR logic - works matching any of the specified genres) |
| sort_by | string Default: "created_at" Enum: "id" "created_at" "stars" "likes_count" "comments_count" Field to sort reviews by |
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string",
- "editorial": false,
- "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "work": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a review by ID.
| review_id required | integer Review ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string",
- "editorial": false,
- "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "work": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}
}Updates a review. Requires authentication; only the author can update their own review.
| review_id required | integer Review ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| work_type | string Enum: "book" "ebook" "audiobook" Type of work being reviewed |
| stars | integer [ 1 .. 5 ] Star rating from 1 to 5 |
| title | string Review title |
| body | string Review content |
{- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string"
}{- "data": {
- "id": 0,
- "slug": "string",
- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string",
- "editorial": false,
- "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "work": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}
}Deletes a review. Requires authentication; only the author can delete their own review.
| review_id required | integer Review ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}| slug required | string The SEO-friendly slug of the review (format: user-name-over-book-title) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string",
- "editorial": false,
- "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "work": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}
}| work_id required | integer Work ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| user_id | integer >= 1 Filter records to those created by the given user ID. |
| stars | integer [ 1 .. 5 ] Filter reviews to those with exactly this many stars (1-5). |
| min_stars | integer [ 1 .. 5 ] Filter reviews to those with stars greater than or equal to this value (1-5). |
| max_stars | integer [ 1 .. 5 ] Filter reviews to those with stars less than or equal to this value (1-5). |
| user_label[] | Array of strings [ 1 .. 3 ] items Items Enum: "normal" "team" "crew" Filter by the review author's user label (OR logic - reviews whose author has any of the specified labels). The frontend "Hebban" filter is user_label[]=team&user_label[]=crew. |
| sort_by | string Default: "created_at" Enum: "id" "created_at" "stars" "likes_count" "comments_count" Field to sort reviews by |
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string",
- "editorial": false,
- "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "work": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}| work_id required | integer Work ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| work_type required | string Enum: "book" "ebook" "audiobook" Type of work being reviewed |
| stars required | integer [ 1 .. 5 ] Star rating from 1 to 5 |
| title required | string Review title |
| body required | string Review content |
{- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string"
}{- "data": {
- "id": 0,
- "slug": "string",
- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string",
- "editorial": false,
- "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "work": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}
}Gets the current user's rating for the work. Requires authentication. Returns 404 if the user has not rated the work.
| work_id required | integer Work ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "rated": true,
- "stars": 1
}Idempotently creates or updates the current user's rating (singleton per user/work). Requires authentication.
| work_id required | integer Work ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| stars required | integer [ 1 .. 5 ] Star rating from 1 to 5 |
{- "stars": 1
}{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Deletes the current user's rating for the work (idempotent). Requires authentication. Returns 204 even if there is no rating to delete. Returns 409 if a review exists for this work by the same user.
| work_id required | integer Work ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Lists reading statuses for the authenticated user, with embedded work data.
Returns reading statuses ordered by most recently added first.
Supports cursor pagination and work sorting via sort_by.
| status required | string Enum: "read" "reading" "want-to-read" Example: reading Reading status filter |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "last_added" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "review_count" "favorite_count" "popularity" "title" "contributor" "last_added" "last_read" "own_rating" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "updated_at": "2025-12-11T15:00:00+00:00",
- "finished_on": "2025-12-01",
- "last_finished_on": "2025-12-01",
- "work": {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}, - "count": 0
}Lists reading statuses for a user, with embedded work data.
Returns reading statuses ordered by most recently added first. Supports cursor pagination.
| user_id required | integer Example: 123 User ID |
| status required | string Enum: "read" "reading" "want-to-read" Example: reading Reading status filter |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "last_added" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "review_count" "favorite_count" "popularity" "title" "contributor" "last_added" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "updated_at": "2025-12-11T15:00:00+00:00",
- "finished_on": "2025-12-01",
- "last_finished_on": "2025-12-01",
- "work": {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}, - "count": 0
}Gets the current user's reading status for the work. Requires authentication.
| work_id required | integer Work ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "status": "want_to_read",
- "finished_on": "2025-12-01"
}
}Creates or updates the current user's reading status (singleton per user/work). Requires authentication. When status is 'read', the finish date is recorded as a read entry (one registration per work per calendar year). If finished_on is omitted, it defaults to today in UTC.
| work_id required | integer Work ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| status required | string (ReadingStatusState) Enum: "want_to_read" "reading" "read" Current reading status for the work. |
| finished_on | string <date> Optional date (YYYY-MM-DD, UTC). Defaults to today in UTC if appending and omitted. |
{- "status": "want_to_read",
- "finished_on": "2019-08-24"
}{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Clears the current user's reading status for the work. Requires authentication. Always returns 204 even if no reading status existed.
| work_id required | integer Work ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Lists the current user's read entries for the work, ordered by finished_on descending. Requires authentication.
| work_id required | integer Work ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "user_id": 0,
- "work_id": 0,
- "finished_on": "2019-08-24",
- "source": "manual",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Creates a read entry. A work is registered once per calendar year: a submission for a year already recorded returns the existing entry instead of creating another. This is not a true idempotent operation, so it still returns 201 Created. Requires authentication.
| work_id required | integer Work ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| finished_on required | string <date> Date when the work was finished (YYYY-MM-DD, UTC) |
| source | string (ReadEntrySource) Default: "manual" Enum: "manual" "import" "challenge" Source of the read entry. |
{- "finished_on": "2019-08-24",
- "source": "manual"
}{- "data": {
- "id": 0,
- "user_id": 0,
- "work_id": 0,
- "finished_on": "2019-08-24",
- "source": "manual",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "challenges": [
- {
- "id": 2025,
- "title": "Hebban Reading Challenge 2024",
- "works": [
- 23,
- 24,
- 25
]
}
], - "lists": [
- {
- "id": 1,
- "visibility": "private",
- "preset": "top",
- "title": "top",
- "works": [
- 11,
- 12,
- 13
]
}, - {
- "id": 6,
- "visibility": "private",
- "preset": null,
- "title": "boeken op zolder",
- "works": [
- 23,
- 24,
- 25
]
}
]
}
}| work required | integer The work ID to check membership against |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "challenges": [
- {
- "id": 2025,
- "title": "Hebban Reading Challenge 2024",
- "contains_work": true
}
], - "lists": [
- {
- "id": 1,
- "visibility": "private",
- "preset": "top",
- "title": "top",
- "contains_work": true
}, - {
- "id": 6,
- "visibility": "private",
- "preset": null,
- "title": "boeken op zolder",
- "contains_work": false
}
]
}
}Lists the current user's personal lists. Requires authentication.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "created_at" Enum: "created_at" "title" "likes_count" "works_count" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| preset | boolean Filter lists by preset status. When |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "title": "string",
- "description": { },
- "visibility": "public",
- "is_preset": true,
- "preset": "top",
- "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Creates a personal list for the current user. Requires authentication.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| title | string |
null or string | |
| visibility | string (ListVisibility) Enum: "public" "private" Visibility for personal book lists. |
{- "title": "My favorite books",
- "description": "Books I can read over and over again",
- "visibility": "public"
}{- "data": {
- "id": 0,
- "title": "string",
- "description": { },
- "visibility": "public",
- "is_preset": true,
- "preset": "top",
- "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Gets a personal list. Requires authentication; owners can always view.
| list_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "title": "string",
- "description": { },
- "visibility": "public",
- "is_preset": true,
- "preset": "top",
- "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Updates a personal list. Requires authentication; only the owner can update.
Preset lists (is_preset: true) have a system-managed title and description that cannot be changed. Only visibility can be updated on preset lists. Sending title or description for a preset list returns 422.
| list_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
| title | string |
null or string | |
| visibility | string (ListVisibility) Enum: "public" "private" Visibility for personal book lists. |
{- "title": "Updated List Title",
- "description": { },
- "visibility": "public"
}{- "data": {
- "id": 0,
- "title": "string",
- "description": { },
- "visibility": "public",
- "is_preset": true,
- "preset": "top",
- "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Deletes a personal list. Requires authentication; only the owner can delete.
| list_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Lists works in one of the current user's personal lists. Requires authentication. Supports work sorting via sort_by.
| list_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "last_added" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "review_count" "favorite_count" "popularity" "title" "contributor" "last_added" "last_read" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}, - "count": 0
}Adds a work to one of the current user's personal lists. Idempotent — repeated calls succeed without side effects. Requires authentication; only the owner can update.
| list_id required | integer |
| work_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Removes a work from one of the current user's personal lists. Requires authentication; only the owner can update.
| list_id required | integer |
| work_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Lists the specified user's personal lists that are PUBLIC. Requires API token.
| user_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "created_at" Enum: "created_at" "title" "likes_count" "works_count" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| preset | boolean Filter lists by preset status. When |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "title": "string",
- "description": { },
- "visibility": "public",
- "is_preset": true,
- "preset": "top",
- "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a user's personal list if it is PUBLIC.
| user_id required | integer |
| list_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "title": "string",
- "description": { },
- "visibility": "public",
- "is_preset": true,
- "preset": "top",
- "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists works in a user's personal list if it is PUBLIC.
| user_id required | integer |
| list_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "last_added" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "review_count" "favorite_count" "popularity" "title" "contributor" "last_added" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Returns all challenges the current user has joined, including their pledge target and progress. Use this to display the user's active and past challenges.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "challenge": {
- "id": 0,
- "year": 2000,
- "title": "string",
- "intro": { },
- "expires_at": { },
- "hero_image": {
- "id": 0,
- "url": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "pledge_target": null,
- "works_count": 0,
- "read_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Join a reading challenge. Optionally set a pledge target (number of books to read). Returns 409 if the user has already joined this challenge, or if the challenge has expired (past its end date) — expired challenges no longer accept participants.
| challenge_id required | integer The ID of the challenge to join |
null or integer >= 1 Optional pledge (number of books to read) |
{- "challenge_id": 0,
- "pledge_target": null
}{- "data": {
- "challenge": {
- "id": 0,
- "year": 2000,
- "title": "string",
- "intro": { },
- "expires_at": { },
- "hero_image": {
- "id": 0,
- "url": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "pledge_target": null,
- "works_count": 0,
- "read_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Returns details about a specific challenge the user has joined, including their pledge target, progress, and the list of works they've added to this challenge.
| challenge_id required | integer The ID of the challenge |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "challenge": {
- "id": 0,
- "year": 2000,
- "title": "string",
- "intro": { },
- "expires_at": { },
- "hero_image": {
- "id": 0,
- "url": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "pledge_target": null,
- "works_count": 0,
- "read_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Update your pledge target (number of books to read) for a challenge you've joined. Returns 409 if the challenge has expired and is read-only.
| challenge_id required | integer The ID of the challenge |
null or integer >= 1 Number of books you pledge to read (null to remove pledge) |
{- "pledge_target": null
}{- "data": {
- "challenge": {
- "id": 0,
- "year": 2000,
- "title": "string",
- "intro": { },
- "expires_at": { },
- "hero_image": {
- "id": 0,
- "url": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "pledge_target": null,
- "works_count": 0,
- "read_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Leave a challenge you've joined. This removes your participation and all works you've added to this challenge. Returns 409 if the challenge has expired and is read-only.
| challenge_id required | integer The ID of the challenge to leave |
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Lists works in the current user's challenge participation list for a given challenge.
Once the challenge has expired, the list is frozen and only returns works with a read
entry linked to that challenge. Other works are no longer part of the frozen list:
they are not returned and no longer counted in works_count, which keeps matching
the number of items returned here. Requires authentication.
| challenge_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "challenge_context": {
- "reading_status": "want_to_read",
- "has_read": true
}
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Adds a work to the current user's challenge participation list. Idempotent — repeated calls succeed without side effects. Requires authentication.
| challenge_id required | integer |
| work_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Removes a work from the current user's challenge participation list. Requires authentication.
| challenge_id required | integer |
| work_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}Lists a user's public challenge participation lists
| user_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "challenge": {
- "id": 0,
- "year": 2000,
- "title": "string",
- "intro": { },
- "expires_at": { },
- "hero_image": {
- "id": 0,
- "url": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "pledge_target": null,
- "works_count": 0,
- "read_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a user's participation in a specific challenge
| user_id required | integer |
| challenge_id required | integer The ID of the challenge |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "challenge": {
- "id": 0,
- "year": 2000,
- "title": "string",
- "intro": { },
- "expires_at": { },
- "hero_image": {
- "id": 0,
- "url": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "pledge_target": null,
- "works_count": 0,
- "read_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists the works a user has added to their challenge participation.
Once the challenge has expired, the list is frozen and only returns works with a read
entry linked to that challenge. Other works are no longer part of the frozen list:
they are not returned and no longer counted in works_count, which keeps matching
the number of items returned here.
| user_id required | integer |
| challenge_id required | integer The ID of the challenge |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "challenge_context": {
- "reading_status": "want_to_read",
- "has_read": true
}
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Search for challenges with support for sorting and pagination
| page | integer >= 1 Default: 1 The page number for traditional pagination (used by search endpoints) |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| query required | string [ 2 .. 255 ] characters Search query (minimum 2 characters) |
| sort_by | string Default: "relevance" Enum: "relevance" "published_at" "title" Field to sort results by. When |
| sort_direction | string (SortDirection) Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "year": 2000,
- "title": "string",
- "intro": { },
- "expires_at": { },
- "hero_image": {
- "id": 0,
- "url": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "current_page": 0,
- "from": 0,
- "last_page": 0,
- "per_page": 0,
- "to": 0,
- "total": 0
}
}Lists challenges available to join, filtered by year.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| from_year | integer [ 2000 .. 2100 ] Default: 2025 Filter challenges from this year onwards (inclusive) |
| sort_direction | string (SortDirection) Default: "desc" Enum: "asc" "desc" Sort direction by year (desc = newest first, asc = oldest first) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "year": 2000,
- "title": "string",
- "intro": { },
- "expires_at": { },
- "hero_image": {
- "id": 0,
- "url": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Returns aggregated statistics for a specific challenge including participant count, total pledges, books read, and completion count.
| challenge required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "participants": 0,
- "total_pledges": 0,
- "books_read": 0,
- "completed": 0
}
}Lists works with cursor-based pagination.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "id" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "read_count_30d" "review_count" "favorite_count" "popularity" "title" "contributor" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| isbn | string [ 4 .. 13 ] characters ^[0-9]{4,13}$ Optional filter on edition ISBN-13. Provide 4–13 digits; results include works whose edition ISBN-13 starts with this prefix. |
| genres[] | Array of integers [ 1 .. 10 ] items Filter by genre IDs (OR logic - works matching any of the specified genres) |
| language | Array of strings Items Enum: "dut" "eng" "other" Filter by language code (ONIX Codelist 74, based on ISO 639-2/B).
Supports single value, comma-separated values, or array syntax.
|
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| publication_date_first_from | string <date> Example: publication_date_first_from=2026-03-10 Include works with publication_date_first on or after this date (YYYY-MM-DD). Works without a first publication date are excluded. |
| publication_date_first_until | string <date> Example: publication_date_first_until=2026-04-09 Include works with publication_date_first on or before this date (YYYY-MM-DD). Works without a first publication date are excluded. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a work by ID.
| work_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Look up a work by its normalized ISBN-13.
The ISBN must be provided as a 13-digit ISBN-13 without separators (no spaces or hyphens).
| isbn required | string = 13 characters ^[0-9]{13}$ 13-digit ISBN-13 without separators. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Fetches multiple works by their IDs in a single request.
Behavior:
ids=1,5,5 returns work 5 twice)Example: GET /works/bulk?ids=1,6,5,5 returns 4 works in order: [1, 6, 5, 5]
| ids required | string^\d+(,\d+)*$ Example: ids=1,6,5,5 Comma-separated list of work IDs (max 100). Duplicates are allowed and will return the same work multiple times. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
]
}Returns works from the "Uitgelicht" (Featured) editorial list. Works are ordered by their position in the list as curated by editors.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
]
}Returns up to 100 works first published in the last 30 days, sorted by popularity (descending). Works with fewer than 2 ratings are excluded so a single rating cannot place a work at the top.
The list is fully algorithmic and refreshes with the current date and platform popularity; no editorial curation applies.
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
]
}Returns up to 100 works that have been recently finished by users across the platform. Each work is shown once, ordered by most recent finish date.
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
]
}Returns up to 100 works that have been recently reviewed by users across the platform. Each work is shown once, ordered by most recent review date.
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
]
}Returns works expected to become available within the next 3 months (configurable).
Upcoming works have:
Works are ordered by publication_date_first ascending (soonest first).
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| isbn | string [ 4 .. 13 ] characters ^[0-9]{4,13}$ Optional filter on edition ISBN-13. Provide 4–13 digits; results include works whose edition ISBN-13 starts with this prefix. |
| genres[] | Array of integers [ 1 .. 10 ] items Filter by genre IDs (OR logic - works matching any of the specified genres) |
| language | Array of strings Items Enum: "dut" "eng" "other" Filter by language code (ONIX Codelist 74, based on ISO 639-2/B).
Supports single value, comma-separated values, or array syntax.
|
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Search for works with support for sorting and pagination
| page | integer >= 1 Default: 1 The page number for traditional pagination (used by search endpoints) |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| query required | string [ 2 .. 255 ] characters Search query (minimum 2 characters) |
| sort_by | string Default: "relevance" Enum: "relevance" "publication_date_first" "publication_date_latest" "title" "ratings_count" "rating_average" "read_count" "read_count_30d" "review_count" "favorite_count" "popularity" "id" Field to sort search results by. When |
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| genres[] | Array of integers [ 1 .. 10 ] items Filter by genre IDs (OR logic - works matching any of the specified genres) |
| language | Array of strings Items Enum: "dut" "eng" "other" Filter by language code (ONIX Codelist 74, based on ISO 639-2/B).
Supports single value, comma-separated values, or array syntax.
|
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "current_page": 0,
- "from": 0,
- "last_page": 0,
- "per_page": 0,
- "to": 0,
- "total": 0
}
}Gets a work by slug.
| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists events for the work with pagination.
| work_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| period | string Default: "future" Enum: "future" "past" "all" Filter events by period. Default is future. |
| sort_by | string Default: "starts_on" Enum: "starts_on" "created_at" Sort column (whitelisted). Defaults to starts_on. |
| sort_direction | string (SortDirection) Default: "desc" Enum: "asc" "desc" Sort direction. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "summary": { },
- "description": { },
- "city": { },
- "meta_title": { },
- "meta_description": { },
- "starts_on": { },
- "starts_at": { },
- "ends_on": { },
- "ends_at": { },
- "access_type": { },
- "price": { },
- "registration_method": { },
- "registration_url": { },
- "registration_email": { },
- "registration_text": { },
- "kind": { },
- "venue_name": { },
- "venue_address": { },
- "venue_url": { },
- "organizer_name": { },
- "organizer_email": { },
- "organizer_url": { },
- "hero_image": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Returns daily Hebban rank snapshots for a work, ordered chronologically (oldest first). Each entry represents the work's rank on a specific date (1 = most popular, up to 10,000). Data is available from November 2018. Works that are not currently ranked may still have historical data.
| work_id required | integer The ID of the work |
| from | string <date> Start date for the history range (inclusive). Defaults to 1 year ago. Must not be in the future. |
| to | string <date> End date for the history range (inclusive). Defaults to today. Must not be in the future. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "ranked_at": "2026-03-15",
- "rank": 42
}
]
}Returns personalized recommendations for a work based on collaborative filtering. First request returns 202 and triggers generation. Subsequent requests return 200 with cached results. Recommendations are grouped into 8 subsets based on author/genre/recency similarity. Failed generation returns 200 with status=failed and error message.
| work_id required | integer The ID of the work |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "work_id": 123,
- "status": "completed",
- "subsets": {
- "same_author_same_genre_recent": [
- 1,
- 2,
- 3,
- 4,
- 5
], - "same_author_same_genre_not_recent": [
- 6,
- 7,
- 8,
- 9,
- 10
], - "same_author_different_genre_recent": [
- 11,
- 12,
- 13,
- 14,
- 15
], - "same_author_different_genre_not_recent": [
- 16,
- 17,
- 18,
- 19,
- 20
], - "different_author_same_genre_recent": [
- 21,
- 22,
- 23,
- 24,
- 25
], - "different_author_same_genre_not_recent": [
- 26,
- 27,
- 28,
- 29,
- 30
], - "different_author_different_genre_recent": [
- 31,
- 32,
- 33,
- 34,
- 35
], - "different_author_different_genre_not_recent": [
- 36,
- 37,
- 38,
- 39,
- 40
]
}, - "error": "Insufficient rating data",
- "generated_at": "2026-01-09T12:00:00Z"
}
}Search for contributors (authors) by name with support for sorting and pagination
| page | integer >= 1 Default: 1 The page number for traditional pagination (used by search endpoints) |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| query required | string [ 2 .. 255 ] characters Search query (minimum 2 characters) |
| sort_by | string Default: "relevance" Enum: "relevance" "name" "followers_count" "works_count" "popularity" Field to sort results by. When |
| sort_direction | string (SortDirection) Default: "asc" Enum: "asc" "desc" Sort direction |
| contributor_role | Array of strings[ items^(?:A01|A12|A13|B01|B05|B06|C01|E07|Z98|Z99)$... ] Example: contributor_role=A01,B06 Filter by ONIX contributor role(s). Accepts comma-separated codes or array. Results include contributors with any of the specified roles (OR logic). Based on ONIX codelist 17 (https://ns.editeur.org/onix/en/17). Codes: A01 (Author), A12 (Illustrator), A13 (Photographer), B01 (Editor), B05 (Adapter), B06 (Translator), C01 (Compiled by), E07 (Narrator), Z98 (Various), Z99 (Other). |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "biography": { },
- "portrait_url": { },
- "portrait_alt_text": { },
- "portrait_attribution": { },
- "user_id": 42,
- "user_slug": "jane-doe",
- "followers_count": 42,
- "works_count": 15,
- "article_count": 8,
- "event_count": 3,
- "roles": [
- "A01",
- "B06"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "current_page": 0,
- "from": 0,
- "last_page": 0,
- "per_page": 0,
- "to": 0,
- "total": 0
}
}Lists contributors with pagination.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "popularity" Enum: "id" "name" "followers_count" "works_count" "popularity" Field to sort contributors by |
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "biography": { },
- "portrait_url": { },
- "portrait_alt_text": { },
- "portrait_attribution": { },
- "user_id": 42,
- "user_slug": "jane-doe",
- "followers_count": 42,
- "works_count": 15,
- "article_count": 8,
- "event_count": 3,
- "roles": [
- "A01",
- "B06"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Fetches multiple contributors by their IDs in a single request.
Behavior:
ids=1,5,5 returns contributor 5 twice)Example: GET /contributors/bulk?ids=1,6,5,5 returns 4 contributors in order: [1, 6, 5, 5]
| ids required | string^\d+(,\d+)*$ Example: ids=1,6,5,5 Comma-separated list of contributor IDs (max 100). Duplicates are allowed and will return the same contributor multiple times. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "biography": { },
- "portrait_url": { },
- "portrait_alt_text": { },
- "portrait_attribution": { },
- "user_id": 42,
- "user_slug": "jane-doe",
- "followers_count": 42,
- "works_count": 15,
- "article_count": 8,
- "event_count": 3,
- "roles": [
- "A01",
- "B06"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Gets a contributor by ID.
| contributor_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "biography": { },
- "portrait_url": { },
- "portrait_alt_text": { },
- "portrait_attribution": { },
- "user_id": 42,
- "user_slug": "jane-doe",
- "followers_count": 42,
- "works_count": 15,
- "article_count": 8,
- "event_count": 3,
- "roles": [
- "A01",
- "B06"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists works for the contributor with pagination.
| contributor_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| contributor_role | string^(?:A01|A12|A13|B01|B05|B06|C01|E07|Z98|Z99)$... Example: contributor_role=A01 Filter by ONIX contributor role. Based on ONIX codelist 17 (https://ns.editeur.org/onix/en/17). Codes: A01 (Author), A12 (Illustrator), A13 (Photographer), B01 (Editor), B05 (Adapter), B06 (Translator), C01 (Compiled by), E07 (Narrator), Z98 (Various), Z99 (Other). |
| sort_by | string Default: "id" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "read_count_30d" "review_count" "favorite_count" "popularity" "title" "contributor" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| isbn | string [ 4 .. 13 ] characters ^[0-9]{4,13}$ Optional filter on edition ISBN-13. Provide 4–13 digits; results include works whose edition ISBN-13 starts with this prefix. |
| genres[] | Array of integers [ 1 .. 10 ] items Filter by genre IDs (OR logic - works matching any of the specified genres) |
| language | Array of strings Items Enum: "dut" "eng" "other" Filter by language code (ONIX Codelist 74, based on ISO 639-2/B).
Supports single value, comma-separated values, or array syntax.
|
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Lists events for the contributor with pagination.
| contributor_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| period | string Default: "future" Enum: "future" "past" "all" Filter events by period. Default is future. |
| sort_by | string Default: "starts_on" Enum: "starts_on" "created_at" Sort column (whitelisted). Defaults to starts_on. |
| sort_direction | string (SortDirection) Default: "desc" Enum: "asc" "desc" Sort direction. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "summary": { },
- "description": { },
- "city": { },
- "meta_title": { },
- "meta_description": { },
- "starts_on": { },
- "starts_at": { },
- "ends_on": { },
- "ends_at": { },
- "access_type": { },
- "price": { },
- "registration_method": { },
- "registration_url": { },
- "registration_email": { },
- "registration_text": { },
- "kind": { },
- "venue_name": { },
- "venue_address": { },
- "venue_url": { },
- "organizer_name": { },
- "organizer_email": { },
- "organizer_url": { },
- "hero_image": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a contributor by slug.
| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "biography": { },
- "portrait_url": { },
- "portrait_alt_text": { },
- "portrait_attribution": { },
- "user_id": 42,
- "user_slug": "jane-doe",
- "followers_count": 42,
- "works_count": 15,
- "article_count": 8,
- "event_count": 3,
- "roles": [
- "A01",
- "B06"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists publishers with pagination.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "gau": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a publisher by ID.
| publisher_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "name": "string",
- "gau": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists works for the publisher with pagination.
| publisher_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "id" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "read_count_30d" "review_count" "favorite_count" "popularity" "title" "contributor" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| isbn | string [ 4 .. 13 ] characters ^[0-9]{4,13}$ Optional filter on edition ISBN-13. Provide 4–13 digits; results include works whose edition ISBN-13 starts with this prefix. |
| genres[] | Array of integers [ 1 .. 10 ] items Filter by genre IDs (OR logic - works matching any of the specified genres) |
| language | Array of strings Items Enum: "dut" "eng" "other" Filter by language code (ONIX Codelist 74, based on ISO 639-2/B).
Supports single value, comma-separated values, or array syntax.
|
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a publisher by slug.
| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "name": "string",
- "gau": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists genres with pagination.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a genre by ID.
| genre_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists works for the genre with pagination.
| genre_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "id" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "read_count_30d" "review_count" "favorite_count" "popularity" "title" "contributor" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| isbn | string [ 4 .. 13 ] characters ^[0-9]{4,13}$ Optional filter on edition ISBN-13. Provide 4–13 digits; results include works whose edition ISBN-13 starts with this prefix. |
| language | Array of strings Items Enum: "dut" "eng" "other" Filter by language code (ONIX Codelist 74, based on ISO 639-2/B).
Supports single value, comma-separated values, or array syntax.
|
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a genre by slug.
| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists the works in a series, paginated. Works are ordered by part number high-to-low; works without a part number follow, newest first.
| slug required | string |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| isbn | string [ 4 .. 13 ] characters ^[0-9]{4,13}$ Optional filter on edition ISBN-13. Provide 4–13 digits; results include works whose edition ISBN-13 starts with this prefix. |
| language | Array of strings Items Enum: "dut" "eng" "other" Filter by language code (ONIX Codelist 74, based on ISO 639-2/B).
Supports single value, comma-separated values, or array syntax.
|
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a series by slug.
| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "title": "string",
- "works_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists the Hebban 1000 entries ordered by rank for a specific year. Defaults to the most recent year that has entries when no year is provided.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| year | integer >= 2018 Filter entries for a specific Hebban 1000 year |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 1,
- "year": 2025,
- "rank": 1,
- "previous_rank": 3,
- "work": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Returns the work IDs of the Hebban 1000 for a specific year, ordered by rank. Defaults to the most recent year that has entries when no year is provided. Intended for clients that need to compute overlap with a user's read books.
| year | integer >= 2018 Filter entries for a specific Hebban 1000 year |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- 0
]
}Search for articles with support for sorting and pagination
| page | integer >= 1 Default: 1 The page number for traditional pagination (used by search endpoints) |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| query required | string [ 2 .. 255 ] characters Search query (minimum 2 characters) |
| type | Array of strings (ArticleType) Items Enum: "news" "interview" "book_of_the_month" "inspiration" "book_club" "opinion" "community" "advertorial" "promotion" "deepdive" "quiz" Filter by type. Accepts single value, comma-separated values, or array syntax.
Examples: |
| sort_by | string Default: "relevance" Enum: "relevance" "published_at" "title" "likes_count" "comments_count" Field to sort results by. When |
| sort_direction | string (SortDirection) Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "title": "string",
- "hero": { },
- "intro": "string",
- "slug": "string",
- "meta_title": { },
- "meta_description": { },
- "type": "news",
- "status": "draft",
- "user": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "current_page": 0,
- "from": 0,
- "last_page": 0,
- "per_page": 0,
- "to": 0,
- "total": 0
}
}| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| status | string Enum: "draft" "scheduled" "published" "archived" Example: status=published Filter by publication status |
| type | Array of strings (ArticleType) Items Enum: "news" "interview" "book_of_the_month" "inspiration" "book_club" "opinion" "community" "advertorial" "promotion" "deepdive" "quiz" Filter by type. Accepts single value, comma-separated values, or array syntax.
Examples: |
| contributor_id | Array of integers <= 10 items [ items >= 1 ] Filter articles to those associated with the given contributor ID(s).
Supports single value, comma-separated, or array syntax (OR logic).
Examples: |
| work_id | Array of integers <= 10 items [ items >= 1 ] Filter articles to those associated with the given work ID(s).
Supports single value, comma-separated, or array syntax (OR logic).
Examples: |
| book_list_id | Array of integers <= 10 items [ items >= 1 ] Filter articles to those associated with the given book list ID(s).
Supports single value, comma-separated, or array syntax (OR logic).
Examples: |
| related_article_id | Array of integers <= 10 items [ items >= 1 ] Filter articles to those that reference or link to the given article ID(s).
Supports single value, comma-separated, or array syntax (OR logic).
Examples: |
| sort_by | string Default: "id" Enum: "id" "created_at" "updated_at" "published_at" "scheduled_at" "title" Field to sort results by. Note: Articles with null values in the sort column are excluded from results. |
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "title": "string",
- "hero": { },
- "intro": "string",
- "slug": "string",
- "meta_title": { },
- "meta_description": { },
- "type": "news",
- "status": "draft",
- "user": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}| article_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "title": "string",
- "hero": { },
- "intro": "string",
- "slug": "string",
- "meta_title": { },
- "meta_description": { },
- "type": "news",
- "status": "draft",
- "user": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "title": "string",
- "hero": { },
- "intro": "string",
- "slug": "string",
- "meta_title": { },
- "meta_description": { },
- "type": "news",
- "status": "draft",
- "user": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Returns curated featured events ordered by position.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "summary": { },
- "description": { },
- "city": { },
- "meta_title": { },
- "meta_description": { },
- "starts_on": { },
- "starts_at": { },
- "ends_on": { },
- "ends_at": { },
- "access_type": { },
- "price": { },
- "registration_method": { },
- "registration_url": { },
- "registration_email": { },
- "registration_text": { },
- "kind": { },
- "venue_name": { },
- "venue_address": { },
- "venue_url": { },
- "organizer_name": { },
- "organizer_email": { },
- "organizer_url": { },
- "hero_image": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Search for events with support for sorting and pagination
| page | integer >= 1 Default: 1 The page number for traditional pagination (used by search endpoints) |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| query required | string [ 2 .. 255 ] characters Search query (minimum 2 characters) |
| sort_by | string Default: "relevance" Enum: "relevance" "starts_on" "title" Field to sort results by. When |
| sort_direction | string (SortDirection) Default: "asc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "summary": { },
- "description": { },
- "city": { },
- "meta_title": { },
- "meta_description": { },
- "starts_on": { },
- "starts_at": { },
- "ends_on": { },
- "ends_at": { },
- "access_type": { },
- "price": { },
- "registration_method": { },
- "registration_url": { },
- "registration_email": { },
- "registration_text": { },
- "kind": { },
- "venue_name": { },
- "venue_address": { },
- "venue_url": { },
- "organizer_name": { },
- "organizer_email": { },
- "organizer_url": { },
- "hero_image": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "current_page": 0,
- "from": 0,
- "last_page": 0,
- "per_page": 0,
- "to": 0,
- "total": 0
}
}| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| period | string Default: "future" Enum: "future" "past" "all" Filter events by period. Default is future. |
| sort_by | string Default: "starts_on" Enum: "starts_on" "created_at" Sort column (whitelisted). Defaults to starts_on. |
| sort_direction | string (SortDirection) Default: "desc" Enum: "asc" "desc" Sort direction. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "summary": { },
- "description": { },
- "city": { },
- "meta_title": { },
- "meta_description": { },
- "starts_on": { },
- "starts_at": { },
- "ends_on": { },
- "ends_at": { },
- "access_type": { },
- "price": { },
- "registration_method": { },
- "registration_url": { },
- "registration_email": { },
- "registration_text": { },
- "kind": { },
- "venue_name": { },
- "venue_address": { },
- "venue_url": { },
- "organizer_name": { },
- "organizer_email": { },
- "organizer_url": { },
- "hero_image": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Lists works for the event with pagination.
| event_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "id" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "read_count_30d" "review_count" "favorite_count" "popularity" "title" "contributor" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| isbn | string [ 4 .. 13 ] characters ^[0-9]{4,13}$ Optional filter on edition ISBN-13. Provide 4–13 digits; results include works whose edition ISBN-13 starts with this prefix. |
| genres[] | Array of integers [ 1 .. 10 ] items Filter by genre IDs (OR logic - works matching any of the specified genres) |
| language | Array of strings Items Enum: "dut" "eng" "other" Filter by language code (ONIX Codelist 74, based on ISO 639-2/B).
Supports single value, comma-separated values, or array syntax.
|
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Lists contributors for the event with pagination.
| event_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "popularity" Enum: "id" "name" "followers_count" "works_count" "popularity" Field to sort contributors by |
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "biography": { },
- "portrait_url": { },
- "portrait_alt_text": { },
- "portrait_attribution": { },
- "user_id": 42,
- "user_slug": "jane-doe",
- "followers_count": 42,
- "works_count": 15,
- "article_count": 8,
- "event_count": 3,
- "roles": [
- "A01",
- "B06"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "title": "string",
- "summary": { },
- "description": { },
- "city": { },
- "meta_title": { },
- "meta_description": { },
- "starts_on": { },
- "starts_at": { },
- "ends_on": { },
- "ends_at": { },
- "access_type": { },
- "price": { },
- "registration_method": { },
- "registration_url": { },
- "registration_email": { },
- "registration_text": { },
- "kind": { },
- "venue_name": { },
- "venue_address": { },
- "venue_url": { },
- "organizer_name": { },
- "organizer_email": { },
- "organizer_url": { },
- "hero_image": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}List published static pages with cursor-based pagination.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "title": "string",
- "hero": { },
- "intro": { },
- "slug": "string",
- "meta_title": { },
- "meta_description": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "is_published": true,
- "published_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}| page_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "title": "string",
- "hero": { },
- "intro": { },
- "slug": "string",
- "meta_title": { },
- "meta_description": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "is_published": true,
- "published_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "title": "string",
- "hero": { },
- "intro": { },
- "slug": "string",
- "meta_title": { },
- "meta_description": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "is_published": true,
- "published_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Search for tags with support for sorting and pagination
| page | integer >= 1 Default: 1 The page number for traditional pagination (used by search endpoints) |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| query required | string [ 2 .. 255 ] characters Search query (minimum 2 characters) |
| sort_by | string Default: "relevance" Enum: "relevance" "articles_count" "name" Field to sort results by. When |
| sort_direction | string (SortDirection) Default: "asc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction",
- "articles_count": 5,
- "events_count": 3,
- "lists_count": 7,
- "works_count": 12,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "current_page": 0,
- "from": 0,
- "last_page": 0,
- "per_page": 0,
- "to": 0,
- "total": 0
}
}Lists tags with pagination.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction",
- "articles_count": 5,
- "events_count": 3,
- "lists_count": 7,
- "works_count": 12,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Gets a tag by ID.
| tag_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 42,
- "name": "fiction",
- "slug": "fiction",
- "articles_count": 5,
- "events_count": 3,
- "lists_count": 7,
- "works_count": 12,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Lists all works associated with a specific tag with pagination.
| tag_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "id" Enum: "id" "publication_date_first" "publication_date_latest" "ratings_count" "rating_average" "read_count" "read_count_30d" "review_count" "favorite_count" "popularity" "title" "contributor" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| isbn | string [ 4 .. 13 ] characters ^[0-9]{4,13}$ Optional filter on edition ISBN-13. Provide 4–13 digits; results include works whose edition ISBN-13 starts with this prefix. |
| genres[] | Array of integers [ 1 .. 10 ] items Filter by genre IDs (OR logic - works matching any of the specified genres) |
| language | Array of strings Items Enum: "dut" "eng" "other" Filter by language code (ONIX Codelist 74, based on ISO 639-2/B).
Supports single value, comma-separated values, or array syntax.
|
| source[] | Array of strings [ 1 .. 3 ] items Items Enum: "cb" "titelbank" "v1" Filter by work source (OR logic - works matching any of the specified sources) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 12345,
- "slug": "de-ontdekking-van-de-kroket-barry-nommish",
- "nstc": "978901234567",
- "title": "De ontdekking van de kroket",
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "language_code": "dut",
- "additional_content": "Tijdloze verhandeling over de kroket.",
- "bestseller_60": "Staat nu al 18 weken op nummer 1, we weten allemaal waarom.",
- "publication_date_first": "1992-01-01",
- "publication_date_latest": "2023-05-15",
- "expected_availability_date": "2026-03-15",
- "availability_status": "available",
- "source": "cb",
- "rating_average": 4.9,
- "ratings_count": 1723,
- "read_count": 542,
- "read_count_30d": 87,
- "hebban_rank": 42,
- "hebban_rank_highest": 15,
- "hebban_1000_rank": 128,
- "is_sponsored": false,
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Lists all articles associated with a specific tag with pagination.
| tag_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| status | string Enum: "draft" "scheduled" "published" "archived" Example: status=published Filter by publication status |
| type | Array of strings (ArticleType) Items Enum: "news" "interview" "book_of_the_month" "inspiration" "book_club" "opinion" "community" "advertorial" "promotion" "deepdive" "quiz" Filter by type. Accepts single value, comma-separated values, or array syntax.
Examples: |
| contributor_id | Array of integers <= 10 items [ items >= 1 ] Filter articles to those associated with the given contributor ID(s).
Supports single value, comma-separated, or array syntax (OR logic).
Examples: |
| work_id | Array of integers <= 10 items [ items >= 1 ] Filter articles to those associated with the given work ID(s).
Supports single value, comma-separated, or array syntax (OR logic).
Examples: |
| book_list_id | Array of integers <= 10 items [ items >= 1 ] Filter articles to those associated with the given book list ID(s).
Supports single value, comma-separated, or array syntax (OR logic).
Examples: |
| related_article_id | Array of integers <= 10 items [ items >= 1 ] Filter articles to those that reference or link to the given article ID(s).
Supports single value, comma-separated, or array syntax (OR logic).
Examples: |
| sort_by | string Default: "id" Enum: "id" "created_at" "updated_at" "published_at" "scheduled_at" "title" Field to sort results by. Note: Articles with null values in the sort column are excluded from results. |
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "title": "string",
- "hero": { },
- "intro": "string",
- "slug": "string",
- "meta_title": { },
- "meta_description": { },
- "type": "news",
- "status": "draft",
- "user": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Lists all events associated with a specific tag with pagination.
| tag_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| period | string Default: "future" Enum: "future" "past" "all" Filter events by period. Default is future. |
| sort_by | string Default: "starts_on" Enum: "starts_on" "created_at" Sort column (whitelisted). Defaults to starts_on. |
| sort_direction | string (SortDirection) Default: "desc" Enum: "asc" "desc" Sort direction. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "summary": { },
- "description": { },
- "city": { },
- "meta_title": { },
- "meta_description": { },
- "starts_on": { },
- "starts_at": { },
- "ends_on": { },
- "ends_at": { },
- "access_type": { },
- "price": { },
- "registration_method": { },
- "registration_url": { },
- "registration_email": { },
- "registration_text": { },
- "kind": { },
- "venue_name": { },
- "venue_address": { },
- "venue_url": { },
- "organizer_name": { },
- "organizer_email": { },
- "organizer_url": { },
- "hero_image": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Lists all book lists associated with a specific tag with pagination.
| tag_id required | integer |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "created_at" Enum: "created_at" "title" "likes_count" "works_count" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "status": "draft",
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "template": { },
- "summary": { },
- "description": { },
- "hero_image": { },
- "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 42,
- "name": "fiction",
- "slug": "fiction",
- "articles_count": 5,
- "events_count": 3,
- "lists_count": 7,
- "works_count": 12,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Returns curated book club campaigns ordered by position.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Returns curated giveaway campaigns ordered by position.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Returns curated featured book club campaigns ordered by position.
Deprecated in favor of GET /curated/book-clubs.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Returns curated featured giveaway campaigns ordered by position.
Deprecated in favor of GET /curated/giveaways.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Search for campaigns with support for sorting and pagination
| page | integer >= 1 Default: 1 The page number for traditional pagination (used by search endpoints) |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| query required | string [ 2 .. 255 ] characters Search query (minimum 2 characters) |
| sort_by | string Default: "relevance" Enum: "relevance" "published_at" "title" Field to sort results by. When |
| sort_direction | string (SortDirection) Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "current_page": 0,
- "from": 0,
- "last_page": 0,
- "per_page": 0,
- "to": 0,
- "total": 0
}
}| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| status | string Enum: "draft" "scheduled" "published" "archived" Example: status=published Filter by publication status |
| type | Array of strings (CampaignType) Items Enum: "giveaway" "book_club" Filter by type. Accepts single value, comma-separated values, or array syntax.
Examples: |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}| campaign_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Returns reviews for the campaign's work written by approved campaign participants only
| campaign_id required | integer Campaign ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| user_id | integer >= 1 Filter records to those created by the given user ID. |
| stars | integer [ 1 .. 5 ] Filter reviews to those with exactly this many stars (1-5). |
| min_stars | integer [ 1 .. 5 ] Filter reviews to those with stars greater than or equal to this value (1-5). |
| max_stars | integer [ 1 .. 5 ] Filter reviews to those with stars less than or equal to this value (1-5). |
| sort_by | string Default: "created_at" Enum: "id" "created_at" "stars" "likes_count" "comments_count" Field to sort reviews by |
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "work_type": "book",
- "stars": 1,
- "title": "string",
- "body": "string",
- "editorial": false,
- "likes_count": 0,
- "comments_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "work": {
- "id": 0,
- "slug": "string",
- "nstc": { },
- "title": "string",
- "subtitle": { },
- "collection_title": { },
- "collection_part_number": { },
- "series_slug": { },
- "annotation": { },
- "description": { },
- "additional_content": { },
- "bestseller_60": { },
- "imprint": { },
- "publisher": { },
- "language_code": { },
- "original_language_code": { },
- "page_count": { },
- "duration_seconds": { },
- "publication_date_first": { },
- "publication_date_latest": { },
- "expected_availability_date": { },
- "availability_status": { },
- "source": "cb",
- "cover_url": { },
- "editions": { },
- "contributors": [
- {
- "id": 0,
- "slug": "string",
- "key_names": "string",
- "names_before_key": { },
- "prefix_to_key": { },
- "contributor_role": "string"
}
], - "genres": [
- {
- "id": 0,
- "slug": "string",
- "name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "subjects": [
- {
- "subject_code": "string",
- "scheme_identifier": "string",
- "scheme_version": { },
- "main_subject": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "campaigns": [
- {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "ratings_count": 0,
- "read_count": 0,
- "read_count_30d": 0,
- "review_count": 0,
- "favorite_count": 0,
- "article_count": 0,
- "event_count": 0,
- "reading_status_read_count": 0,
- "reading_status_reading_count": 0,
- "reading_status_want_to_read_count": 0,
- "rating_average": { },
- "ratings_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "hebban_rank": { },
- "hebban_rank_highest": { },
- "hebban_1000_rank": { },
- "sponsored_from": { },
- "sponsored_until": { },
- "is_sponsored": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Submit to a campaign. This endpoint is idempotent: if the user has already submitted to this campaign, the existing submission is returned with a 200 status instead of creating a duplicate.
| campaign required | integer Campaign ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
required | object Flexible form data |
{- "data": { }
}{- "id": 0,
- "campaign": {
- "id": 0,
- "slug": "string",
- "type": "giveaway",
- "status": "draft",
- "campaign_status": { },
- "title": "string",
- "intro": { },
- "description": { },
- "forum_link": { },
- "hero": { },
- "work": { },
- "coordinator": { },
- "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "published_at": { },
- "scheduled_at": { },
- "starts_at": { },
- "ends_at": { },
- "submissions_count": 0,
- "rating_average": { },
- "rating_distribution": {
- "1": 0,
- "2": 0,
- "3": 0,
- "4": 0,
- "5": 0
}, - "meta_title": { },
- "meta_description": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "user": {
- "id": 123,
- "name": "John Doe",
- "slug": "john-doe",
- "user_label": "normal",
- "profile_visibility": "public",
- "followers_count": 123,
- "following_count": 45,
- "reviews_count": 78,
- "challenges_count": 2,
- "reading_status_read_count": 42,
- "reading_status_reading_count": 3,
- "reading_status_want_to_read_count": 15,
- "created_at": "2024-01-15T10:30:00+00:00",
- "updated_at": "2025-01-15T10:30:00+00:00"
}, - "data": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Lists posts for a campaign in one chronological stream, ordered by display_at (the publication date for a live post, the scheduled date for an upcoming one) with id as tiebreaker — so the intro post appears first and upcoming posts naturally follow the live ones. Every item has the same shape; upcoming posts carry upcoming: true with empty blocks (content stays private until live) and a null published_at, and their detail endpoint still returns 404 until they go live. Draft posts are never included.
| campaign_id required | integer Campaign ID |
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "campaign_id": 0,
- "title": "string",
- "upcoming": true,
- "hero_image": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "comments_closed": true,
- "comments_count": 0,
- "display_at": "2019-08-24T14:15:22Z",
- "published_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Returns a single campaign post, including its content blocks. Returns 404 for a post that doesn't exist or isn't live — draft and scheduled posts are indistinguishable from posts that don't exist.
| campaign_post_id required | integer Campaign post ID |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "campaign_id": 0,
- "title": "string",
- "upcoming": true,
- "hero_image": { },
- "blocks": [
- {
- "id": 0,
- "type": "text",
- "data": {
- "text": "string"
}, - "order": 0
}
], - "comments_closed": true,
- "comments_count": 0,
- "display_at": "2019-08-24T14:15:22Z",
- "published_at": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Returns curated editorial book lists for the app ordered by position.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "status": "draft",
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "template": { },
- "summary": { },
- "description": { },
- "hero_image": { },
- "works": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Returns curated editorial book lists for the homepage ordered by position.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "status": "draft",
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "template": { },
- "summary": { },
- "description": { },
- "hero_image": { },
- "works": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Returns curated editorial book lists for the homepage ordered by position.
Deprecated in favor of GET /curated/homepage/lists.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "status": "draft",
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "template": { },
- "summary": { },
- "description": { },
- "hero_image": { },
- "works": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Search for book lists with support for sorting and pagination
| page | integer >= 1 Default: 1 The page number for traditional pagination (used by search endpoints) |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| query required | string [ 2 .. 255 ] characters Search query (minimum 2 characters) |
| sort_by | string Default: "relevance" Enum: "relevance" "title" "created_at" "works_count" "likes_count" Field to sort results by. When |
| sort_direction | string (SortDirection) Default: "asc" Enum: "asc" "desc" Sort direction |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "status": "draft",
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "template": { },
- "summary": { },
- "description": { },
- "hero_image": { },
- "works": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "current_page": 0,
- "from": 0,
- "last_page": 0,
- "per_page": 0,
- "to": 0,
- "total": 0
}
}| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| sort_by | string Default: "created_at" Enum: "created_at" "title" "likes_count" "works_count" Field to sort results by.
|
| sort_direction | string Default: "desc" Enum: "asc" "desc" Sort direction |
| status | string Enum: "draft" "scheduled" "published" "archived" Example: status=published Filter by publication status |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "id": 0,
- "slug": "string",
- "title": "string",
- "status": "draft",
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "template": { },
- "summary": { },
- "description": { },
- "hero_image": { },
- "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}| list_id required | integer |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "title": "string",
- "status": "draft",
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "template": { },
- "summary": { },
- "description": { },
- "hero_image": { },
- "works": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| slug required | string |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "id": 0,
- "slug": "string",
- "title": "string",
- "status": "draft",
- "published_at": { },
- "scheduled_at": { },
- "expires_at": { },
- "template": { },
- "summary": { },
- "description": { },
- "hero_image": { },
- "works": { },
- "tags": [
- {
- "id": 42,
- "name": "fiction",
- "slug": "fiction"
}
], - "likes_count": 0,
- "works_count": 0,
- "preview_works": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Returns active slides for a specific set, ordered by position.
Only returns slides where is_active is true and current date is within the active_from/active_until range. This filtering is always applied server-side and cannot be modified via query parameters.
| cursor | string Encoded cursor for cursor-based pagination |
| per_page | integer [ 1 .. 250 ] Default: 20 The number of items per page. |
| set required | string (SlideSet) Enum: "homepage" "books" "authors" "events" "reading_clubs" "theme_banner" The slide set to retrieve (e.g., homepage, books, authors) |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": [
- {
- "alt_text": "Hebban verwenst je een fijne kerstdinges!",
- "set": "homepage"
}
], - "links": {
}, - "meta": {
- "per_page": 0,
- "next_cursor": "string",
- "prev_cursor": "string"
}
}Returns public statistics about the Hebban community.
Statistics are precomputed hourly and cached. The cached_at field indicates
when the data was last calculated.
Last 30 days stats use a rolling 30-day window.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "last_30_days": {
- "new_members": 2372,
- "challenge_participants": 1161,
- "reviews": 512,
- "ratings": 2048,
- "works": 350
}, - "all_time": {
- "books_read": 8601471,
- "reviews": 377777,
- "ratings": 6625458,
- "members": 395000,
- "works": 389000,
- "book_lists": 200000
}, - "cached_at": "2025-11-28T16:00:00Z"
}
}Returns the current health status of the API and its dependencies.
This endpoint does not require authentication or the Accept: application/json header.
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "data": {
- "status": "healthy",
- "checks": {
- "property1": {
- "status": "healthy",
- "duration_ms": 12,
- "error": "Database connection failed: Connection refused"
}, - "property2": {
- "status": "healthy",
- "duration_ms": 12,
- "error": "Database connection failed: Connection refused"
}
}, - "app": {
- "version": "2.0.33",
- "environment": "production"
}
}
}Checks whether a short-lived preview_id token is currently valid. Used by the frontend before rendering article and page previews.
| preview_id required | string <uuid> Short-lived preview token UUID generated by Filament. |
| X-Request-Id | string^[0-7][0-9A-HJKMNP-TV-Z]{25}$ Example: 01J9Z1Q4R7Z7B4M5X6C7D8E9FA Optional client-provided correlation identifier (ULID).
|
{- "title": "Unauthenticated",
- "status": 401,
- "request_id": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "code": "auth.unauthenticated",
- "type": "about:blank",
- "detail": "Already joined this challenge.",
- "instance": "01J9Z1Q4R7Z7B4M5X6C7D8E9FA",
- "errors": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}