← Back to KitabHub
API v1 — Generally Available

KitabHub API
Build with Books

Integrate reading data, book metadata, and literary social features into your app. One API. Bilingual. Built for the Arab world and beyond.

Quick Start

All API requests require an API key passed in the Authorization header. Generate a key in the My API Keys section below.

bash
curl -H "Authorization: Bearer kb_live_..." \
  "https://kitabhub.app/api/v1/books/search?q=نجيب+محفوظ"

Authentication

Pass your API key in the Authorization header using the Bearer scheme:

http
Authorization: Bearer kb_live_<your_key>

Rate Limits

PlanRequests / minuteRequests / day
Free602,000
Premium30050,000

Response Format

All responses are JSON. Successful responses return the requested resource wrapped in a top-level key (e.g. { "books": [...] }). Errors return { "error": "..." }.

Error Codes

StatusNameMeaning
400Bad RequestMissing or invalid query parameter
401UnauthorizedMissing or invalid API key
403ForbiddenResource is private
404Not FoundResource does not exist
409ConflictDuplicate resource or constraint violation
429Too Many RequestsRate limit exceeded
500Server ErrorUnexpected server error

Endpoints

Books

GET/api/v1/books/search

Search books by title, author, or ISBN across the KitabHub catalogue and external sources.

ParameterTypeRequiredDescription
qstringrequiredSearch query (min 2 chars). Supports Arabic and English.
limitnumberoptionalMax results to return (1–20, default 10).
sourcestringoptional"all" | "local" | "external". Defaults to "all".
json
// Response
{
  "books": [
    {
      "id": "clx...",
      "title": "أولاد حارتنا",
      "author": "نجيب محفوظ",
      "cover": "https://...",
      "isbn": "978-977-419-975-0",
      "rating": 4.6,
      "ratingCount": 1840,
      "genre": ["Literary Fiction", "Arabic Literature"],
      "language": "ar",
      "_source": "kitabhub"
    }
  ],
  "total": 1
}
GET/api/v1/books/{id}

Retrieve full metadata for a specific book by its KitabHub ID.

ParameterTypeRequiredDescription
idstringrequiredBook ID (path param).
json
// Response
{
  "book": {
    "id": "clx...",
    "title": "أولاد حارتنا",
    "author": "نجيب محفوظ",
    "description": "...",
    "cover": "https://...",
    "isbn": "978-977-419-975-0",
    "rating": 4.6,
    "ratingCount": 1840,
    "genre": ["Literary Fiction"],
    "language": "ar",
    "pageCount": 432,
    "publisher": "دار الشروق",
    "hasAudiobook": false,
    "_count": { "reviews": 412, "shelfBooks": 3800 }
  }
}
GET/api/v1/books/trending

Returns up to 20 trending books based on reads, want-to-reads, reviews, and currently-reading activity over the past 7 days. Cached for 1 hour.

json
// Response
{
  "books": [
    {
      "id": "clx...",
      "title": "...",
      "author": "...",
      "cover": "https://...",
      "rating": 4.3,
      "genre": ["..."],
      "trendingScore": 248
    }
  ]
}

Users (Public Profiles)

GET/api/v1/users/{handle}

Retrieve the public profile of a KitabHub user by their handle. Private accounts return only minimal info.

ParameterTypeRequiredDescription
handlestringrequiredThe user's @handle (without the @).
json
// Response
{
  "user": {
    "id": "clx...",
    "handle": "naguib_m",
    "name": "نجيب محفوظ",
    "bio": "Nobel Prize laureate...",
    "image": "https://...",
    "isVerifiedAuthor": true,
    "genres": ["Literary Fiction", "Arabic Literature"],
    "_count": { "followers": 14200, "following": 3, "bookReviews": 0 }
  }
}
GET/api/v1/users/{handle}/shelf

Returns the public bookshelf of a user. Returns 403 if the user has set their shelves to private.

ParameterTypeRequiredDescription
handlestringrequiredUser handle.
shelfstringoptionalFilter to a specific shelf: "Read" | "Currently Reading" | "Want to Read".
limitnumberoptionalMax books per shelf (1–50, default 20).
cursorstringoptionalPagination cursor from previous response.

Clubs

GET/api/v1/clubs

List all public reading clubs. Supports search and genre filtering.

ParameterTypeRequiredDescription
searchstringoptionalSearch clubs by name or description.
genrestringoptionalFilter by genre tag.
pagenumberoptionalPage number (default 1).
limitnumberoptionalResults per page (1–50, default 20).
GET/api/v1/clubs/{id}

Retrieve details of a specific public reading club.

ParameterTypeRequiredDescription
idstringrequiredClub ID (path param).

Code Examples

curl

bash
curl -H "Authorization: Bearer kb_live_..." \
  "https://kitabhub.app/api/v1/books/search?q=نجيب+محفوظ"

JavaScript / TypeScript

javascript
const response = await fetch(
  "https://kitabhub.app/api/v1/books/search?q=Naguib+Mahfouz",
  { headers: { "Authorization": "Bearer kb_live_..." } }
);
const { books } = await response.json();
console.log(books[0].title); // "Children of the Alley"

Python

python
import requests

resp = requests.get(
    "https://kitabhub.app/api/v1/books/search",
    params={"q": "Naguib Mahfouz"},
    headers={"Authorization": "Bearer kb_live_..."},
)
books = resp.json()["books"]
print(books[0]["title"])  # Children of the Alley

RSS & Atom Feeds

KitabHub exposes standard syndication feeds so any RSS reader or aggregator can track a user's reading activity or a book club's updates — no API key required. Feeds are cached for 30 minutes and only available for public profiles.

Profile feeds

GET/api/rss/{handle}RSS 2.0
GET/api/atom/{handle}Atom 1.0

Returns up to 50 recent reading events for a public user profile — books added to the Read shelf, currently-reading starts, published reviews, and reading milestones. Both feeds carry the same content; choose the format your toolchain prefers.

html
<!-- Auto-discovered by browsers & readers from the profile <head> -->
<link rel="alternate" type="application/rss+xml"
      title="@naguib_m on KitabHub"
      href="https://kitabhub.app/api/rss/naguib_m" />
<link rel="alternate" type="application/atom+xml"
      title="@naguib_m on KitabHub"
      href="https://kitabhub.app/api/atom/naguib_m" />

Book club feed

GET/api/rss/club/{id}RSS 2.0

Returns recent activity for a public book club: new members, finished books (with average member ratings), new discussions, and upcoming meetings.

Feed item typeExample title
New memberSara Al-Rashid joined Fiction Fridays
Finished bookFiction Fridays finished reading “Frankenstein in Baghdad”
New discussionNew discussion about “The Alchemist” in Fiction Fridays
Upcoming meetingUpcoming meeting: October Wrap-Up — Fiction Fridays

Webhooks

Webhooks let you receive real-time HTTP POST notifications when activity happens on a KitabHub account. Your endpoint must be HTTPS. Managing webhooks requires a valid API key (see My API Keys).

Available events

EventFired whenPayload fields
shelf.addA book is added to any shelfbookId, bookTitle, shelf, shelfBookId
review.createA new book review is publishedbookId, rating, reviewId
goal.completeA reading goal target is reachedyear, target, booksRead, goalId

Managing webhooks

GET/api/developer/webhooksList webhooks
POST/api/developer/webhooksCreate webhook (returns secret once)
DELETE/api/developer/webhooks?id=Delete a webhook
javascript
// Create a webhook
const res = await fetch("https://kitabhub.app/api/developer/webhooks", {
  method: "POST",
  headers: {
    "Authorization": "Bearer kb_live_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://your-app.com/hooks/kitabhub",
    events: ["shelf.add", "review.create"],
  }),
});

const { webhook, signingSecret } = await res.json();
// signingSecret is shown ONCE — store it securely

Verifying webhook signatures

Every request includes an X-KitabHub-Signature header containing an HMAC-SHA256 signature of the raw request body, prefixed with sha256=. Always verify this before trusting the payload.

JavaScript / Node.js

javascript
import crypto from "crypto";

export function verifyKitabHubSignature(
  body: string,       // raw request body (string, not parsed)
  signature: string,  // X-KitabHub-Signature header value
  secret: string,     // your signing secret
): boolean {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret)
          .update(body)
          .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature),
  );
}

Python

python
import hmac
import hashlib

def verify_kitabhub_signature(
    body: bytes,       # raw request body bytes
    signature: str,    # X-KitabHub-Signature header
    secret: str,
) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(),
        body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

The X-KitabHub-Event header also identifies the event type (e.g. shelf.add) so you can route quickly without parsing the body first.

My API Keys

Sign in to generate API keys

Create a free KitabHub account to get your personal API key and start building.

Support

Help & Documentation

Questions about the API? Visit our help center or contact us directly.

Help Center →

Contact

For API-specific questions, partnership enquiries, or to report issues.

Get in touch →