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 } } }"}'
GraphQL lets you request exactly the fields you need. All examples below show the available fields — pick only the ones you want.

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.

MUTATIONlogin
Authenticate with email and password. Returns a JWT token.
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>
MUTATIONregister
Create a new account. Returns a JWT token like login.
mutation {
  register(
    email: "you@example.com"
    password: "your-password"
    name: "Your Name"
    handle: "yourhandle"
    languages: ["en"]
  ) {
    token
    profile { id handle }
  }
}

Books

QUERYbookBySlug
Look up a book by its URL slug.
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 }
  }
}
QUERYbookById
Look up a book by its ID.
query {
  bookById(id: "BOOK_ID") {
    id
    title
    authors { id name }
  }
}
QUERYbookByIsbn
Look up a book by ISBN-10 or ISBN-13.
query {
  bookByIsbn(isbn: "9780062316110") {
    id
    title
    slug
    cover
    authors { name }
  }
}
QUERYbookByRandom
Get a random book.
query {
  bookByRandom {
    id
    title
    slug
    cover
    authors { name }
  }
}
QUERYbooksBySlugs
Look up multiple books by their slugs.
query {
  booksBySlugs(slugs: ["slug-one", "slug-two"]) {
    id
    title
    slug
    cover
    authors { name }
  }
}
QUERYgetEditionsByBookId
Get all editions (formats, languages) of a book.
query {
  getEditionsByBookId(
    bookId: "BOOK_ID"
    languages: ["en"]
    audiobook: false
    limit: 10
    offset: 0
  ) {
    id
    title
    isbn13
    language
    physicalFormat
    cover
  }
}
QUERYmyBooks
Get all books in your library. Requires authentication.
query {
  myBooks(
    limit: 50
    offset: 0
    sortBy: recency
    sortDirection: desc
    search: "optional search term"
  ) {
    id
    title
    slug
    cover
    authors { name }
  }
}
ArgumentTypeDescription
sortByBookSortingrecency, title, author, or readingStatus
sortDirectionSortDirectionasc or desc
QUERYmyBooksByReadingState
Get your books filtered by reading status. Requires authentication.
query {
  myBooksByReadingState(
    limit: 20
    offset: 0
    readingStatus: IS_READING
    sortBy: recency
    sortDirection: desc
  ) {
    id
    title
    slug
    cover
    authors { name }
  }
}
QUERYbooksByReadingStateAndProfile
Get any user's books by reading status (public).
query {
  booksByReadingStateAndProfile(
    profileId: "PROFILE_ID"
    readingStatus: WANTS_TO_READ
    limit: 20
    offset: 0
  ) {
    id
    title
    cover
    authors { name }
  }
}
MUTATIONcreateBook
Add a new book to the catalog. Requires authentication.
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.



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

WANTS_TO_READIS_READINGFINISHEDDROPPEDNONE
QUERYmyReadingStates
Get all your reading states. Requires authentication.
query {
  myReadingStates {
    id
    status
    bookId
    createdAt
    book {
      title
      slug
      cover
      authors { name }
    }
  }
}
MUTATIONupdateReadingState
Update your reading status for a book.
mutation {
  updateReadingState(
    bookId: "BOOK_ID"
    readingStatus: IS_READING
  ) {
    id
    status
    book { title }
  }
}
MUTATIONupdateReadingProgress
Track your reading progress within a book.
mutation {
  updateReadingProgress(
    bookId: "BOOK_ID"
    progress: 142
    capacity: 320
    unit: page
  ) {
    id
    progress
    capacity
    completed
  }
}

The unit can be page or percent.

QUERYreadingProgresses
Get reading progress for specific books.
query {
  readingProgresses(
    bookIds: ["BOOK_ID_1", "BOOK_ID_2"]
    active: true
  ) {
    bookId
    progress
    capacity
    unit
    completed
  }
}

Reviews

QUERYreview
Get a specific user's review for a book.
query {
  review(bookId: "BOOK_ID", profileId: "PROFILE_ID") {
    id
    rating
    text
    spoiler
    tags
    createdAt
    profile { handle name }
    book { title }
  }
}
QUERYgetUserReviews
Get all reviews by a user.
query {
  getUserReviews(
    profileId: "PROFILE_ID"
    limit: 20
    offset: 0
  ) {
    ... on BookReviewActivity {
      id
      review {
        rating
        text
        tags
      }
      book {
        title
        slug
        cover
      }
    }
  }
}
MUTATIONcreateReview
Write a review for a book. Requires authentication.
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.

MUTATIONupdateReview
Update an existing review.
mutation {
  updateReview(
    id: "REVIEW_ID"
    rating: 4.5
    text: "Updated review text."
    spoiler: false
    tags: ["brilliant"]
  ) {
    id
    rating
    text
  }
}
MUTATIONdeleteReview
Delete a review.
mutation {
  deleteReview(reviewId: "REVIEW_ID")
}

Highlights

Highlights (moments) let you save quotes, passages, and notes from books.

QUERYmomentById
Get a highlight by ID.
query {
  momentById(id: "MOMENT_ID") {
    id
    quote
    note
    where
    spoiler
    createdAt
    book { title slug }
    profile { handle name }
  }
}
QUERYmyMoments
Get your highlights. Requires authentication.
query {
  myMoments(limit: 20, offset: 0) {
    ... on MomentActivity {
      moment {
        id
        quote
        note
        where
      }
      book {
        title
        slug
      }
    }
  }
}
MUTATIONcreateMoment
Create a new highlight. Requires authentication.
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
  }
}
MUTATIONupdateMoment
Update an existing highlight.
mutation {
  updateMoment(
    momentId: "MOMENT_ID"
    bookId: "BOOK_ID"
    quote: "Updated quote."
    note: "Updated note."
    where: "Chapter 3"
    spoiler: false
  ) {
    id
    quote
    note
  }
}
MUTATIONdeleteMoment
Delete a highlight.
mutation {
  deleteMoment(momentId: "MOMENT_ID")
}

Shelves

Shelves are user-curated lists of books.

QUERYgetShelfBySlug
Get a shelf by its URL slug.
query {
  getShelfBySlug(slug: "SHELF_SLUG") {
    id
    slug
    title
    description
    books { id title cover authors { name } }
    owner { handle name }
  }
}
QUERYgetShelvesByProfileId
Get all shelves for a user.
query {
  getShelvesByProfileId(
    profileId: "PROFILE_ID"
    limit: 20
    offset: 0
  ) {
    id
    slug
    title
    description
  }
}
QUERYbooksByShelf
Get books on a shelf with sorting and search.
query {
  booksByShelf(
    shelfSlug: "SHELF_SLUG"
    limit: 20
    offset: 0
    sortBy: recency
    sortDirection: desc
  ) {
    id
    title
    slug
    cover
    authors { name }
  }
}
MUTATIONcreateShelf
Create a new shelf. Requires authentication.
mutation {
  createShelf(
    title: "My Favorite Sci-Fi"
    description: "The best science fiction books."
  ) {
    id
    slug
    title
  }
}
MUTATIONaddBookToShelf
Add a book to a shelf.
mutation {
  addBookToShelf(
    bookId: "BOOK_ID"
    shelfId: "SHELF_ID"
  ) {
    id
    title
  }
}
MUTATIONremoveBookFromShelf
Remove a book from a shelf.
mutation {
  removeBookFromShelf(
    bookId: "BOOK_ID"
    shelfId: "SHELF_ID"
  ) {
    id
  }
}

Profiles

QUERYme
Get the current authenticated user's profile.
query {
  me {
    email
    languages
    profile {
      id
      handle
      name
      bio
      image
      followerCount
      followingCount
    }
  }
}
QUERYprofileByHandle
Look up a user by handle.
query {
  profileByHandle(handle: "piet") {
    id
    handle
    name
    bio
    image
    followerCount
    followingCount
  }
}
QUERYprofileById
Look up a user by ID.
query {
  profileById(id: "PROFILE_ID") {
    id
    handle
    name
    bio
    image
  }
}
MUTATIONupdateMe
Update your profile. Requires authentication.
mutation {
  updateMe(
    handle: "yourhandle"
    name: "Your Name"
    bio: "Book lover."
    languages: ["en", "de"]
  ) {
    profile { handle name bio }
  }
}
MUTATIONfollowProfile
Follow a user. Requires authentication.
mutation {
  followProfile(followingProfileId: "PROFILE_ID")
}
MUTATIONunfollowProfile
Unfollow a user. Requires authentication.
mutation {
  unfollowProfile(followingProfileId: "PROFILE_ID")
}

Authors

QUERYauthorBySlug
Look up an author by URL slug.
query {
  authorBySlug(slug: "yuval-noah-harari-4lz3t") {
    id
    name
    slug
    description
    image
  }
}
QUERYbooksByAuthor
Get all books by an author.
query {
  booksByAuthor(
    authorId: "AUTHOR_ID"
    limit: 20
    offset: 0
  ) {
    id
    title
    slug
    cover
    publishedDate
  }
}

Clubs

Book clubs for reading and discussing books together.

QUERYclubByHandle
Look up a club by its handle.
query {
  clubByHandle(handle: "club-handle") {
    id
    handle
    name
    description
    image
    membershipCount
    bookCount
    languages
    createdAt
  }
}
QUERYgetFeaturedClubs
Get the list of featured clubs.
query {
  getFeaturedClubs {
    id
    handle
    name
    description
    image
    membershipCount
  }
}
QUERYgetClubsByProfileId
Get all clubs a user is a member of.
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.

QUERYgoalBySlug
Look up a goal by its slug.
query {
  goalBySlug(slug: "GOAL_SLUG") {
    id
    name
    slug
    target
    startDate
    endDate
    autoUpdate
    participants { id }
    createdBy { handle name }
  }
}
MUTATIONcreateGoal
Create a reading goal. Requires authentication.
mutation {
  createGoal(
    name: "2026 Reading Challenge"
    target: 24
    startDate: "2026-01-01"
    endDate: "2026-12-31"
    autoUpdate: true
  ) {
    id
    goal { slug name target }
  }
}

Social Interactions

MUTATIONlikeTarget
Like a review, highlight, club post, or comment.
mutation {
  likeTarget(
    targetId: "TARGET_ID"
    targetType: Review
  ) {
    success
  }
}

The targetType can be Review, Moment, ClubPost, Comment, Activity, or Goal.

MUTATIONaddComment
Add a comment to a review, highlight, or club post.
mutation {
  addComment(
    targetId: "TARGET_ID"
    targetType: Review
    text: "Great review!"
  ) {
    id
    text
    createdAt
    profile { handle }
  }
}

Activity Feed

QUERYaggregatedFeed
Get the aggregated activity feed for a user. Shows reading activity, reviews, highlights, and more.
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

FieldTypeDescription
idID!Unique identifier
slugString!URL slug
titleString!Book title
subtitleStringSubtitle
descriptionStringBook description/blurb
coverStringCover image URL
isbn10StringISBN-10
isbn13StringISBN-13
languageString!ISO language code
pageCountIntNumber of pages
publishedDateDateTimePublication date
publisherStringPublisher name
physicalFormatStringhardcover, paperback, ebook, audio
authors[Author!]!List of authors
workIdStringID of the parent work (groups editions)

Author

FieldTypeDescription
idID!Unique identifier
nameString!Author name
slugStringURL slug
descriptionStringAuthor bio
imageStringAuthor photo URL

Profile

FieldTypeDescription
idID!Unique identifier
handleString!Username
nameString!Display name
bioStringUser bio
imageStringAvatar URL
followerCountIntNumber of followers
followingCountIntNumber of profiles following

ReadingState

FieldTypeDescription
idID!Unique identifier
statusReadingStatus!Current reading status
bookIdString!Associated book
profileIdString!User who owns this state
createdAtDateTime!When the status was set

Review

FieldTypeDescription
idID!Unique identifier
ratingFloat!Rating (0.0 to 5.0)
textStringReview text
spoilerBoolean!Whether it contains spoilers
tags[String!]!Review tags
createdAtDateTime!When the review was created

Moment (Highlight)

FieldTypeDescription
idID!Unique identifier
quoteStringThe quoted passage
noteStringUser's note about the passage
whereStringLocation in the book
spoilerBoolean!Whether it contains spoilers
createdAtDateTime!When the highlight was created

Shelf

FieldTypeDescription
idID!Unique identifier
slugString!URL slug
titleString!Shelf name
descriptionStringShelf description
books[Book!]!Books on the shelf
ownerProfile!Shelf owner

Club

FieldTypeDescription
idID!Unique identifier
handleString!Club handle for URLs
nameString!Club name
descriptionStringClub description
imageStringClub image URL
membershipCountIntNumber of members
bookCountIntNumber of books in the club
languages[String!]!Club languages

Enums

ReadingStatus

WANTS_TO_READIS_READINGFINISHEDDROPPEDNONE

BookSorting

recencytitleauthorreadingStatus

ReactionTarget

ReviewMomentClubPostCommentActivityGoal

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.