API Documentation
Literal exposes a public GraphQL API that you can use to search books, manage reading lists, build widgets, and create integrations. All data on Literal is accessible through this API.
Getting Started
The API is a single GraphQL endpoint:
https://literal.club/graphql/
All requests are POST requests with a JSON body containing query and optional variables. Most read operations are available without authentication. Write operations and access to personal data require a Bearer token.
Example Request
curl -X POST https://literal.club/graphql/ \
-H "Content-Type: application/json" \
-d '{"query": "{ bookBySlug(slug: \"sapiens-yuval-noah-harari-pv7la\") { title authors { name } } }"}'Example with Authentication
curl -X POST https://literal.club/graphql/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"query": "{ me { profile { handle name } } }"}'Authentication
Authenticate by calling the login mutation. It returns a JWT token that you include in subsequent requests as a Bearer token in the Authorization header.
mutation {
login(email: "you@example.com", password: "your-password") {
token
email
languages
profile {
id
handle
name
bio
image
}
}
}Use the returned token in the Authorization header for authenticated requests:
Authorization: Bearer <token>
mutation {
register(
email: "you@example.com"
password: "your-password"
name: "Your Name"
handle: "yourhandle"
languages: ["en"]
) {
token
profile { id handle }
}
}Books
query {
bookBySlug(slug: "sapiens-yuval-noah-harari-pv7la") {
id
slug
title
subtitle
description
cover
isbn10
isbn13
language
pageCount
publishedDate
publisher
physicalFormat
workId
authors { id name slug }
}
}query {
bookById(id: "BOOK_ID") {
id
title
authors { id name }
}
}query {
bookByIsbn(isbn: "9780062316110") {
id
title
slug
cover
authors { name }
}
}query {
bookByRandom {
id
title
slug
cover
authors { name }
}
}query {
booksBySlugs(slugs: ["slug-one", "slug-two"]) {
id
title
slug
cover
authors { name }
}
}query {
getEditionsByBookId(
bookId: "BOOK_ID"
languages: ["en"]
audiobook: false
limit: 10
offset: 0
) {
id
title
isbn13
language
physicalFormat
cover
}
}query {
myBooks(
limit: 50
offset: 0
sortBy: recency
sortDirection: desc
search: "optional search term"
) {
id
title
slug
cover
authors { name }
}
}| Argument | Type | Description |
|---|---|---|
| sortBy | BookSorting | recency, title, author, or readingStatus |
| sortDirection | SortDirection | asc or desc |
query {
myBooksByReadingState(
limit: 20
offset: 0
readingStatus: IS_READING
sortBy: recency
sortDirection: desc
) {
id
title
slug
cover
authors { name }
}
}query {
booksByReadingStateAndProfile(
profileId: "PROFILE_ID"
readingStatus: WANTS_TO_READ
limit: 20
offset: 0
) {
id
title
cover
authors { name }
}
}mutation {
createBook(
title: "Book Title"
description: "A description of the book."
authors: "Author Name"
language: "en"
isbn13: "9781234567890"
cover: "https://example.com/cover.jpg"
pageCount: "320"
publishedDate: "2024-01-15"
publisher: "Publisher Name"
physicalFormat: "hardcover"
)
}Returns the URL of the created book. Authors should be comma-separated if there are multiple. The physicalFormat can be hardcover, paperback, ebook, or audio.
Search
query {
searchBookV2(query: "Sapiens") {
id
title
slug
cover
authors { name }
}
}query {
searchProfiles(query: "username") {
id
handle
name
image
}
}query {
searchClubs(query: "science fiction") {
id
handle
name
description
membershipCount
}
}query {
searchShelves(query: "philosophy") {
id
slug
title
}
}Reading States
A reading state tracks the relationship between a user and a book: whether they want to read it, are currently reading it, finished it, or dropped it.
Reading Status Values
query {
myReadingStates {
id
status
bookId
createdAt
book {
title
slug
cover
authors { name }
}
}
}mutation {
updateReadingState(
bookId: "BOOK_ID"
readingStatus: IS_READING
) {
id
status
book { title }
}
}mutation {
updateReadingProgress(
bookId: "BOOK_ID"
progress: 142
capacity: 320
unit: page
) {
id
progress
capacity
completed
}
}The unit can be page or percent.
query {
readingProgresses(
bookIds: ["BOOK_ID_1", "BOOK_ID_2"]
active: true
) {
bookId
progress
capacity
unit
completed
}
}Reviews
query {
review(bookId: "BOOK_ID", profileId: "PROFILE_ID") {
id
rating
text
spoiler
tags
createdAt
profile { handle name }
book { title }
}
}query {
getUserReviews(
profileId: "PROFILE_ID"
limit: 20
offset: 0
) {
... on BookReviewActivity {
id
review {
rating
text
tags
}
book {
title
slug
cover
}
}
}
}mutation {
createReview(
bookId: "BOOK_ID"
rating: 4.0
text: "A fascinating exploration of..."
spoiler: false
tags: ["thought-provoking", "well-researched"]
) {
id
rating
text
}
}Rating is a float from 0.0 to 5.0, in 0.5 increments.
mutation {
updateReview(
id: "REVIEW_ID"
rating: 4.5
text: "Updated review text."
spoiler: false
tags: ["brilliant"]
) {
id
rating
text
}
}mutation {
deleteReview(reviewId: "REVIEW_ID")
}Highlights
Highlights (moments) let you save quotes, passages, and notes from books.
query {
momentById(id: "MOMENT_ID") {
id
quote
note
where
spoiler
createdAt
book { title slug }
profile { handle name }
}
}query {
myMoments(limit: 20, offset: 0) {
... on MomentActivity {
moment {
id
quote
note
where
}
book {
title
slug
}
}
}
}mutation {
createMoment(
bookId: "BOOK_ID"
quote: "The passage you want to highlight."
note: "Your thoughts about this passage."
where: "Chapter 3, p. 42"
spoiler: false
) {
id
quote
note
createdAt
}
}mutation {
updateMoment(
momentId: "MOMENT_ID"
bookId: "BOOK_ID"
quote: "Updated quote."
note: "Updated note."
where: "Chapter 3"
spoiler: false
) {
id
quote
note
}
}mutation {
deleteMoment(momentId: "MOMENT_ID")
}Shelves
Shelves are user-curated lists of books.
query {
getShelfBySlug(slug: "SHELF_SLUG") {
id
slug
title
description
books { id title cover authors { name } }
owner { handle name }
}
}query {
getShelvesByProfileId(
profileId: "PROFILE_ID"
limit: 20
offset: 0
) {
id
slug
title
description
}
}query {
booksByShelf(
shelfSlug: "SHELF_SLUG"
limit: 20
offset: 0
sortBy: recency
sortDirection: desc
) {
id
title
slug
cover
authors { name }
}
}mutation {
createShelf(
title: "My Favorite Sci-Fi"
description: "The best science fiction books."
) {
id
slug
title
}
}mutation {
addBookToShelf(
bookId: "BOOK_ID"
shelfId: "SHELF_ID"
) {
id
title
}
}mutation {
removeBookFromShelf(
bookId: "BOOK_ID"
shelfId: "SHELF_ID"
) {
id
}
}Profiles
query {
me {
email
languages
profile {
id
handle
name
bio
image
followerCount
followingCount
}
}
}query {
profileByHandle(handle: "piet") {
id
handle
name
bio
image
followerCount
followingCount
}
}query {
profileById(id: "PROFILE_ID") {
id
handle
name
bio
image
}
}mutation {
updateMe(
handle: "yourhandle"
name: "Your Name"
bio: "Book lover."
languages: ["en", "de"]
) {
profile { handle name bio }
}
}mutation {
followProfile(followingProfileId: "PROFILE_ID")
}mutation {
unfollowProfile(followingProfileId: "PROFILE_ID")
}Authors
query {
authorBySlug(slug: "yuval-noah-harari-4lz3t") {
id
name
slug
description
image
}
}query {
booksByAuthor(
authorId: "AUTHOR_ID"
limit: 20
offset: 0
) {
id
title
slug
cover
publishedDate
}
}Clubs
Book clubs for reading and discussing books together.
query {
clubByHandle(handle: "club-handle") {
id
handle
name
description
image
membershipCount
bookCount
languages
createdAt
}
}query {
getFeaturedClubs {
id
handle
name
description
image
membershipCount
}
}query {
getClubsByProfileId(
profileId: "PROFILE_ID"
limit: 20
offset: 0
) {
id
handle
name
image
membershipCount
}
}Goals
Reading goals to track how many books you want to read in a given period.
query {
goalBySlug(slug: "GOAL_SLUG") {
id
name
slug
target
startDate
endDate
autoUpdate
participants { id }
createdBy { handle name }
}
}mutation {
createGoal(
name: "2026 Reading Challenge"
target: 24
startDate: "2026-01-01"
endDate: "2026-12-31"
autoUpdate: true
) {
id
goal { slug name target }
}
}Activity Feed
query {
aggregatedFeed(
profileId: "PROFILE_ID"
limit: 20
offset: 0
) {
id
verb
activity_count
actor_count
activities {
id
verb
object
object_type
time
}
}
}Types Reference
Book
| Field | Type | Description |
|---|---|---|
| id | ID! | Unique identifier |
| slug | String! | URL slug |
| title | String! | Book title |
| subtitle | String | Subtitle |
| description | String | Book description/blurb |
| cover | String | Cover image URL |
| isbn10 | String | ISBN-10 |
| isbn13 | String | ISBN-13 |
| language | String! | ISO language code |
| pageCount | Int | Number of pages |
| publishedDate | DateTime | Publication date |
| publisher | String | Publisher name |
| physicalFormat | String | hardcover, paperback, ebook, audio |
| authors | [Author!]! | List of authors |
| workId | String | ID of the parent work (groups editions) |
Author
| Field | Type | Description |
|---|---|---|
| id | ID! | Unique identifier |
| name | String! | Author name |
| slug | String | URL slug |
| description | String | Author bio |
| image | String | Author photo URL |
Profile
| Field | Type | Description |
|---|---|---|
| id | ID! | Unique identifier |
| handle | String! | Username |
| name | String! | Display name |
| bio | String | User bio |
| image | String | Avatar URL |
| followerCount | Int | Number of followers |
| followingCount | Int | Number of profiles following |
ReadingState
| Field | Type | Description |
|---|---|---|
| id | ID! | Unique identifier |
| status | ReadingStatus! | Current reading status |
| bookId | String! | Associated book |
| profileId | String! | User who owns this state |
| createdAt | DateTime! | When the status was set |
Review
| Field | Type | Description |
|---|---|---|
| id | ID! | Unique identifier |
| rating | Float! | Rating (0.0 to 5.0) |
| text | String | Review text |
| spoiler | Boolean! | Whether it contains spoilers |
| tags | [String!]! | Review tags |
| createdAt | DateTime! | When the review was created |
Moment (Highlight)
| Field | Type | Description |
|---|---|---|
| id | ID! | Unique identifier |
| quote | String | The quoted passage |
| note | String | User's note about the passage |
| where | String | Location in the book |
| spoiler | Boolean! | Whether it contains spoilers |
| createdAt | DateTime! | When the highlight was created |
Shelf
| Field | Type | Description |
|---|---|---|
| id | ID! | Unique identifier |
| slug | String! | URL slug |
| title | String! | Shelf name |
| description | String | Shelf description |
| books | [Book!]! | Books on the shelf |
| owner | Profile! | Shelf owner |
Club
| Field | Type | Description |
|---|---|---|
| id | ID! | Unique identifier |
| handle | String! | Club handle for URLs |
| name | String! | Club name |
| description | String | Club description |
| image | String | Club image URL |
| membershipCount | Int | Number of members |
| bookCount | Int | Number of books in the club |
| languages | [String!]! | Club languages |
Enums
ReadingStatus
BookSorting
ReactionTarget
Rate Limits & Guidelines
- Be respectful with request volume. If you need bulk data access, reach out to us.
- Cache responses where possible.
- Use field selection to request only what you need — this is a major advantage of GraphQL.
- For questions or issues, contact us at hello@literal.club.


Social Interactions
mutation { likeTarget( targetId: "TARGET_ID" targetType: Review ) { success } }The
targetTypecan beReview,Moment,ClubPost,Comment,Activity, orGoal.mutation { addComment( targetId: "TARGET_ID" targetType: Review text: "Great review!" ) { id text createdAt profile { handle } } }