Smart Library Docs

Circulation Endpoints

Detailed API reference for circulation operations — issuing books, processing returns, viewing history, and listing active loans.

Circulation Endpoints

Base path: /api/v1/circulation Authentication: All routes require a valid JWT token.


POST /circulation/issue

Issues a book copy to a user, creating an active loan transaction.

Access Control

  • Allowed roles: ROLE_ADMIN, ROLE_LIBRARIAN

Request

POST /api/v1/circulation/issue
Authorization: Bearer <token>
Content-Type: application/json
{
  "userId": "64b8f3a2e7d1c...",
  "bookCopyId": "64c9a1b2c3d4e..."
}
FieldTypeRequiredDescription
userIdstringMongoDB ObjectId of the borrowing user
bookCopyIdstringMongoDB ObjectId of the physical book copy

What Happens

  1. Validates the BookCopy exists and has status AVAILABLE
  2. Updates BookCopy status to CHECKED_OUT
  3. Creates a Transaction record with:
    • issuedAt: Current date/time
    • dueDate: 14 days from now
    • returnedAt: null (loan is active)

Response — 201 Created

{
  "transaction": {
    "_id": "64d1f...",
    "userId": "64b8f3a2...",
    "bookCopyId": "64c9a1b2...",
    "issuedAt": "2026-07-03T12:00:00.000Z",
    "dueDate": "2026-07-17T12:00:00.000Z",
    "returnedAt": null,
    "renewalCount": 0
  }
}

Error Responses

StatusBodyWhen
400{ "error": "Book copy not available" }Copy doesn't exist or isn't AVAILABLE

POST /circulation/return

Processes a book return, closing the active transaction.

Access Control

  • Allowed roles: ROLE_ADMIN, ROLE_LIBRARIAN

Request

POST /api/v1/circulation/return
Authorization: Bearer <token>
Content-Type: application/json
{
  "transactionId": "64d1f..."
}
FieldTypeRequiredDescription
transactionIdstringMongoDB ObjectId of the active transaction

What Happens

  1. Finds the Transaction by ID
  2. Validates the transaction exists and hasn't been returned yet
  3. Sets returnedAt to current date/time
  4. Updates the associated BookCopy status back to AVAILABLE

Response — 200 OK

{
  "transaction": {
    "_id": "64d1f...",
    "userId": "64b8f3a2...",
    "bookCopyId": "64c9a1b2...",
    "issuedAt": "2026-07-03T12:00:00.000Z",
    "dueDate": "2026-07-17T12:00:00.000Z",
    "returnedAt": "2026-07-10T14:30:00.000Z",
    "renewalCount": 0
  }
}

Error Responses

StatusBodyWhen
400{ "error": "Invalid or already returned transaction" }Transaction not found or already has returnedAt

GET /circulation/history

Returns borrowing history, filtered by user role.

Access Control

  • Allowed roles: Any authenticated user
  • Data filtering: Students see only their own history; Admins/Librarians see all

Request

GET /api/v1/circulation/history
Authorization: Bearer <token>

Role-Based Filtering

const where = req.user.role === 'ROLE_STUDENT'
  ? { userId: req.user.id }
  : {};

Response — 200 OK

{
  "history": [
    {
      "_id": "64d1f...",
      "userId": "64b8f3a2...",
      "issuedAt": "2026-07-03T12:00:00.000Z",
      "dueDate": "2026-07-17T12:00:00.000Z",
      "returnedAt": null,
      "bookCopyId": {
        "_id": "64c9a...",
        "barcode": "B-10045",
        "status": "CHECKED_OUT",
        "bookId": {
          "_id": "64c8e...",
          "title": "Clean Code",
          "author": "Robert C. Martin"
        }
      }
    }
  ]
}

Population Chain

The response deeply populates bookCopyId → bookId to provide the full book title and metadata without additional API calls.

Sorting

Results are sorted by issuedAt in descending order (newest first).


GET /circulation/active

Returns all currently active (unreturned) loans system-wide.

Access Control

  • Allowed roles: ROLE_ADMIN, ROLE_LIBRARIAN

Request

GET /api/v1/circulation/active
Authorization: Bearer <token>

Response — 200 OK

{
  "active": [
    {
      "_id": "64d1f...",
      "userId": {
        "_id": "64b8f...",
        "firstName": "John",
        "lastName": "Doe",
        "email": "john@university.edu"
      },
      "bookCopyId": {
        "_id": "64c9a...",
        "barcode": "B-10045",
        "bookId": {
          "_id": "64c8e...",
          "title": "Clean Code"
        }
      },
      "issuedAt": "2026-07-03T12:00:00.000Z",
      "dueDate": "2026-07-17T12:00:00.000Z",
      "returnedAt": null
    }
  ]
}

Filter

Transaction.find({ returnedAt: null })

Only transactions where returnedAt is null (book has not been returned) are included.

On this page