PublishDrive

Example: Ebook Upload

End-to-end walkthrough — create an ebook, upload EPUB and cover files, and publish to stores using the PublishDrive Distribution API.

This guide walks through the complete lifecycle of publishing an ebook: creating the book record, uploading the EPUB manuscript and cover image, and publishing to distribution channels. Every request uses curl against the staging environment.

Replace YOUR_API_KEY with your actual API key. All UUIDs and presigned URLs shown here are examples — your responses will contain unique values.

See also: List books, Get a book, Update a book, Upload API primer, Unpublish and delete.

Prerequisites

  • A valid PublishDrive API key (request one from support)
  • An EPUB file for the ebook content
  • A cover image (JPEG or PNG, minimum 1400 × 2100 px recommended)
  • SHA-256 hashes of both files

Computing file hashes

shasum -a 256 my-novel.epub
shasum -a 256 cover.jpg

Full Flow

Step 1 — Create the book record

Send a POST request to /books with the ebook metadata. Required fields: format, title, language, description, category, copyright, saleTerritory, publicationDate, contributor, and price.

Request

curl -X POST https://api.sandbox.dev.publishdrive.com/v2/distribution/books \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "ebook",
    "title": "The Great Adventure",
    "subtitle": "A Journey Through Time",
    "language": ["en"],
    "description": "An epic tale of discovery and wonder spanning three continents and two centuries.",
    "category": ["FIC002000", "FIC014000"],
    "keyword": ["adventure", "historical fiction", "epic"],
    "copyright": "SELF",
    "saleTerritory": ["ALL"],
    "publicationDate": "2026-06-15",
    "contributor": [
      {
        "firstName": "Jane",
        "lastName": "Doe",
        "role": "Author"
      },
      {
        "firstName": "John",
        "lastName": "Smith",
        "role": "Editor"
      }
    ],
    "price": [
      { "currency": "USD", "price": 9.99 },
      { "currency": "EUR", "price": 8.99 },
      { "currency": "GBP", "price": 7.99 }
    ]
  }'

Response 201 Created

{
  "bookId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Save the bookId — you need it for every subsequent call.

Step 2 — Request upload URLs for the EPUB and cover

Send a POST to /books/{bookPublicId}/upload with an array describing each file. Use role ebook_content for the manuscript and ebook_cover for the cover image.

Request

curl -X POST https://api.sandbox.dev.publishdrive.com/v2/distribution/books/a1b2c3d4-e5f6-7890-abcd-ef1234567890/upload \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "referenceId": "epub-ref",
      "role": "ebook_content",
      "filename": "my-novel.epub",
      "hashSha256": "9c50bbd0c11fda120232a970f3ee67f993459bb81fda6f35d7ac4cfa9b45d5f5"
    },
    {
      "referenceId": "cover-ref",
      "role": "ebook_cover",
      "filename": "cover.jpg",
      "hashSha256": "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
    }
  ]'

Response 201 Created

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "type": "book-file-upload",
      "attributes": {
        "referenceId": "epub-ref",
        "role": "ebook_content",
        "url": "https://s3.amazonaws.com/bucket/presigned-epub-url?...",
        "expiresAt": "2026-06-10T12:00:00Z"
      }
    },
    {
      "id": "660f9500-f3ac-52e5-b827-557766551111",
      "type": "book-file-upload",
      "attributes": {
        "referenceId": "cover-ref",
        "role": "ebook_cover",
        "url": "https://s3.amazonaws.com/bucket/presigned-cover-url?...",
        "expiresAt": "2026-06-10T12:00:00Z"
      }
    }
  ]
}

Each item gives you:

  • id — the fileId you will use in the complete and attach steps
  • url — the presigned S3 URL to PUT your file bytes to
  • expiresAt — deadline for the upload (presigned URLs are time-limited)

Step 3 — Upload file bytes to the presigned URLs

Use HTTP PUT to upload each file directly to its presigned URL. No API key header is needed — the URL itself carries authorization.

Upload the EPUB

curl -X PUT "https://s3.amazonaws.com/bucket/presigned-epub-url?..." \
  -H "Content-Type: application/epub+zip" \
  --data-binary @my-novel.epub

Upload the cover

curl -X PUT "https://s3.amazonaws.com/bucket/presigned-cover-url?..." \
  -H "Content-Type: image/jpeg" \
  --data-binary @cover.jpg

Presigned URLs expire. Upload promptly after requesting them. If one expires, request a new URL with a fresh call to the upload endpoint.

Step 4 — Attach each file to the book

After the bytes are on S3, confirm each upload and link it to the book in one call: PATCH /books/{bookPublicId}/file/{fileId}/attach with the original filename and the same hashSha256 you used when requesting the upload URL. The book will not reference the asset until this call succeeds. If the uploaded bytes do not match the declared hash, the API returns 422.

Attach the EPUB

curl -X PATCH https://api.sandbox.dev.publishdrive.com/v2/distribution/books/a1b2c3d4-e5f6-7890-abcd-ef1234567890/file/550e8400-e29b-41d4-a716-446655440000/attach \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "my-novel.epub",
    "hashSha256": "9c50bbd0c11fda120232a970f3ee67f993459bb81fda6f35d7ac4cfa9b45d5f5"
  }'

Attach the cover

curl -X PATCH https://api.sandbox.dev.publishdrive.com/v2/distribution/books/a1b2c3d4-e5f6-7890-abcd-ef1234567890/file/660f9500-f3ac-52e5-b827-557766551111/attach \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "cover.jpg",
    "hashSha256": "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
  }'

Response 200 OK (for each)

{}

Step 5 — Publish the book

Once metadata and files are complete, send the book to distribution channels.

Request

curl -X POST https://api.sandbox.dev.publishdrive.com/v2/distribution/books/a1b2c3d4-e5f6-7890-abcd-ef1234567890/publish \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response 204 No Content

The book is now queued for distribution to all stores enabled in your territory settings.


Verify the book status

After publishing, retrieve the book to confirm its state.

curl -X GET https://api.sandbox.dev.publishdrive.com/v2/distribution/books/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "apikey: YOUR_API_KEY"

Quick reference

StepMethodEndpointPurpose
1POST/booksCreate book record with metadata
2POST/books/{id}/uploadGet presigned URLs for files
3PUT(presigned URL)Upload raw bytes to S3
4PATCH/books/{id}/file/{fileId}/attachConfirm upload and link file to book
5POST/books/{id}/publishSend to distribution

Common errors

StatusMeaningFix
401Missing or invalid API keyCheck the apikey header
404Book or file not foundVerify the bookPublicId or fileId
409Presigned URL already usedRequest a new upload URL
422Validation errorCheck the detail field in the Problem response for missing/invalid fields

On this page