Example: Audiobook Upload
End-to-end walkthrough — create an audiobook, upload audio tracks and cover art, define chapters, and publish to stores using the PublishDrive Distribution API.
This guide walks through the complete lifecycle of publishing an audiobook: creating the book record with audio-specific metadata, uploading individual audio tracks and the cover image, wiring tracks to chapters, and publishing. 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)
- Audio content files (MP3 or M4A/M4B) — one file per chapter
- A cover image (JPEG or PNG, minimum 2400 × 2400 px, square aspect ratio recommended for audiobooks)
- SHA-256 hashes of all files
Computing file hashes
shasum -a 256 chapter-01.mp3
shasum -a 256 chapter-02.mp3
shasum -a 256 chapter-03.mp3
shasum -a 256 audiobook-cover.jpgFull Flow
Step 1 — Create the audiobook record
Send a POST request to /books with format set to audio. Include the audioDetails object for audiobook-specific fields and at least one contributor with a Narrated by role.
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": "audio",
"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. Narrated by award-winning voice actor James Wilson.",
"category": ["FIC002000", "FIC014000"],
"keyword": ["adventure", "historical fiction", "audiobook"],
"copyright": "SELF",
"saleTerritory": ["ALL"],
"publicationDate": "2026-07-01",
"audioDetails": {
"audioEdition": "UBR"
},
"contributor": [
{
"firstName": "Jane",
"lastName": "Doe",
"role": "Author"
},
{
"firstName": "James",
"lastName": "Wilson",
"role": "Narrated by"
}
],
"price": [
{ "currency": "USD", "price": 19.99 },
{ "currency": "EUR", "price": 17.99 },
{ "currency": "GBP", "price": 15.99 }
]
}'Response 201 Created
{
"bookId": "b2c3d4e5-f6a7-8901-bcde-f23456789012"
}Save the bookId — every subsequent call needs it.
audioDetails fields
| Field | Type | Description |
|---|---|---|
audioLength | integer | Total runtime in seconds (e.g. 32400 = 9 hours) |
audioEdition | string | UBR (unabridged) or ABR (abridged) |
Step 2 — Request upload URLs for audio tracks and cover
Send a POST to /books/{bookPublicId}/upload with one entry per file. Use role audio_content for each audio track and audio_cover for the cover image.
Request
curl -X POST https://api.sandbox.dev.publishdrive.com/v2/distribution/books/b2c3d4e5-f6a7-8901-bcde-f23456789012/upload \
-H "apikey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"referenceId": "ch01",
"role": "audio_content",
"filename": "chapter-01.mp3",
"hashSha256": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
},
{
"referenceId": "ch02",
"role": "audio_content",
"filename": "chapter-02.mp3",
"hashSha256": "b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3"
},
{
"referenceId": "ch03",
"role": "audio_content",
"filename": "chapter-03.mp3",
"hashSha256": "c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4"
},
{
"referenceId": "cover-ref",
"role": "audio_cover",
"filename": "audiobook-cover.jpg",
"hashSha256": "d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5"
}
]'Response 201 Created
{
"data": [
{
"id": "11111111-aaaa-bbbb-cccc-111111111111",
"type": "book-file-upload",
"attributes": {
"referenceId": "ch01",
"role": "audio_content",
"url": "https://s3.amazonaws.com/bucket/presigned-ch01?...",
"expiresAt": "2026-07-01T12:00:00Z"
}
},
{
"id": "22222222-aaaa-bbbb-cccc-222222222222",
"type": "book-file-upload",
"attributes": {
"referenceId": "ch02",
"role": "audio_content",
"url": "https://s3.amazonaws.com/bucket/presigned-ch02?...",
"expiresAt": "2026-07-01T12:00:00Z"
}
},
{
"id": "33333333-aaaa-bbbb-cccc-333333333333",
"type": "book-file-upload",
"attributes": {
"referenceId": "ch03",
"role": "audio_content",
"url": "https://s3.amazonaws.com/bucket/presigned-ch03?...",
"expiresAt": "2026-07-01T12:00:00Z"
}
},
{
"id": "44444444-aaaa-bbbb-cccc-444444444444",
"type": "book-file-upload",
"attributes": {
"referenceId": "cover-ref",
"role": "audio_cover",
"url": "https://s3.amazonaws.com/bucket/presigned-cover?...",
"expiresAt": "2026-07-01T12:00:00Z"
}
}
]
}Save each id — these are the fileId values you need for the complete, attach, and chapter steps.
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.
Upload Chapter 1
curl -X PUT "https://s3.amazonaws.com/bucket/presigned-ch01?..." \
-H "Content-Type: audio/mpeg" \
--data-binary @chapter-01.mp3Upload Chapter 2
curl -X PUT "https://s3.amazonaws.com/bucket/presigned-ch02?..." \
-H "Content-Type: audio/mpeg" \
--data-binary @chapter-02.mp3Upload Chapter 3
curl -X PUT "https://s3.amazonaws.com/bucket/presigned-ch03?..." \
-H "Content-Type: audio/mpeg" \
--data-binary @chapter-03.mp3Upload the cover
curl -X PUT "https://s3.amazonaws.com/bucket/presigned-cover?..." \
-H "Content-Type: image/jpeg" \
--data-binary @audiobook-cover.jpgPresigned URLs expire. Upload all files promptly after requesting them. If one expires, request a new URL with a fresh call to the upload endpoint.
For audiobooks with many chapters, you can upload multiple files in parallel — each presigned URL is independent.
Step 4 — Attach each file to the book
After the bytes are on S3, confirm each upload and link it to the book with PATCH /books/{bookPublicId}/file/{fileId}/attach using the same filename and hashSha256 you used when requesting URLs.
Attach Chapter 1
curl -X PATCH https://api.sandbox.dev.publishdrive.com/v2/distribution/books/b2c3d4e5-f6a7-8901-bcde-f23456789012/file/11111111-aaaa-bbbb-cccc-111111111111/attach \
-H "apikey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "chapter-01.mp3",
"hashSha256": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
}'Attach Chapter 2
curl -X PATCH https://api.sandbox.dev.publishdrive.com/v2/distribution/books/b2c3d4e5-f6a7-8901-bcde-f23456789012/file/22222222-aaaa-bbbb-cccc-222222222222/attach \
-H "apikey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "chapter-02.mp3",
"hashSha256": "b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3"
}'Attach Chapter 3
curl -X PATCH https://api.sandbox.dev.publishdrive.com/v2/distribution/books/b2c3d4e5-f6a7-8901-bcde-f23456789012/file/33333333-aaaa-bbbb-cccc-333333333333/attach \
-H "apikey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "chapter-03.mp3",
"hashSha256": "c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4"
}'Attach the cover
curl -X PATCH https://api.sandbox.dev.publishdrive.com/v2/distribution/books/b2c3d4e5-f6a7-8901-bcde-f23456789012/file/44444444-aaaa-bbbb-cccc-444444444444/attach \
-H "apikey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "audiobook-cover.jpg",
"hashSha256": "d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5"
}'Response 200 OK (for each)
{}Step 5 — Define chapters via Update Book
Audiobook chapters are not created by the upload or attach calls. You must explicitly map each audio content file to a chapter by calling PATCH /books/{bookPublicId} with a chapters array.
Each chapter entry requires:
| Field | Type | Description |
|---|---|---|
fileId | UUID | The fileId of the attached audio content file |
sequence | integer | Chapter order (1-based); acts as the upsert key |
title | string | Chapter display title |
titleAscii | string | ASCII-only version of the title (optional, use when title contains non-ASCII characters) |
Request
curl -X PATCH https://api.sandbox.dev.publishdrive.com/v2/distribution/books/b2c3d4e5-f6a7-8901-bcde-f23456789012 \
-H "apikey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chapters": [
{
"fileId": "11111111-aaaa-bbbb-cccc-111111111111",
"sequence": 1,
"title": "Chapter 1: The Beginning"
},
{
"fileId": "22222222-aaaa-bbbb-cccc-222222222222",
"sequence": 2,
"title": "Chapter 2: The Journey"
},
{
"fileId": "33333333-aaaa-bbbb-cccc-333333333333",
"sequence": 3,
"title": "Chapter 3: The Arrival"
}
]
}'Response 200 OK
{
"bookId": "b2c3d4e5-f6a7-8901-bcde-f23456789012"
}Each audio content file must belong to exactly one chapter. Make sure every attached audio content file is assigned to a chapter before publishing.
Step 6 — Publish the audiobook
Once all files are attached and chapters are defined, send the audiobook to distribution.
Request
curl -X POST https://api.sandbox.dev.publishdrive.com/v2/distribution/books/b2c3d4e5-f6a7-8901-bcde-f23456789012/publish \
-H "apikey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'Response 204 No Content
The audiobook is now queued for distribution to all stores enabled in your territory settings.
Verify the audiobook status
After publishing, retrieve the book to confirm its state and chapter assignments.
curl -X GET https://api.sandbox.dev.publishdrive.com/v2/distribution/books/b2c3d4e5-f6a7-8901-bcde-f23456789012 \
-H "apikey: YOUR_API_KEY"Quick reference
| Step | Method | Endpoint | Purpose |
|---|---|---|---|
| 1 | POST | /books | Create audiobook with format: "audio" and audioDetails |
| 2 | POST | /books/{id}/upload | Get presigned URLs for audio tracks + cover |
| 3 | PUT | (presigned URL) | Upload raw bytes to S3 |
| 4 | PATCH | /books/{id}/file/{fileId}/attach | Confirm upload and link each file |
| 5 | PATCH | /books/{id} | Define chapters mapping tracks to sequence |
| 6 | POST | /books/{id}/publish | Send to distribution |
Key differences from ebook upload
| Aspect | Ebook | Audiobook |
|---|---|---|
| Format | ebook | audio |
| Content role | ebook_content (single EPUB) | audio_content (one per chapter) |
| Cover role | ebook_cover | audio_cover |
| Extra metadata | — | audioDetails with audioLength and audioEdition |
| Chapters | Not applicable | Required — map each audio file to a chapter via Update Book |
| Contributor | Author, Editor, etc. | Must include at least one Narrated by contributor |
Common errors
| Status | Meaning | Fix |
|---|---|---|
401 | Missing or invalid API key | Check the apikey header |
404 | Book or file not found | Verify the bookPublicId or fileId |
409 | Presigned URL already used | Request a new upload URL |
422 | Validation error | Check the detail field — common causes: missing chapters, mismatched fileId in chapter definition, missing narrator contributor |
Example: Ebook Upload
End-to-end walkthrough — create an ebook, upload EPUB and cover files, and publish to stores using the PublishDrive Distribution API.
Example: Print on demand upload
End-to-end walkthrough — create a print book, upload interior PDF and cover assets, and publish using the PublishDrive Distribution API.
