POD API onboarding guide

Connect your server to Shrutgyan’s print-on-demand service. Quote a job, submit it once, and track its receipt.

Your integration address is supplied privately by Shrutgyan. Every example uses POD_API_URL as a placeholder for that address.

All balances, quotes, and charges are in Indian rupees (INR). Amount fields ending in _minor use paise: 100 paise = ₹1.00.

One order can contain 1–20 different books for one recipient in India. Printing is deducted from your prepaid balance when the whole order is accepted. Shipping charges are confirmed and settled separately with our team before dispatch.

Get access

  1. Create a Shrutgyan customer account and give our team the registered email address.
  2. Ask our team to enable POD client access and approve the exact hostnames where you store print-ready PDFs.
  3. Arrange prepaid credit. Our team adds it manually; your account cannot add its own balance.
  4. Open My account → Print on demand. Generate a named API key and copy it immediately. Confirm your login password when generating a key.
  5. Get your integration address privately from our team and save it as POD_API_URL on your server.

Keys expire after 90 days by default; choose 1–365 days. Up to five keys can be active per account. A full key is shown only once. If you lose it, revoke it and generate another.

Authenticate every request

X-POD-Key: YOUR_SECRET_API_KEY
Accept: application/json

Use HTTPS and call the API from your backend. Store the key in a secret manager or environment variable. Keep it out of frontend JavaScript, mobile app bundles, source control, URLs, screenshots, and application logs.

Do not use WordPress application passwords or the Authorization header for this API. Browser-origin requests and URL query parameters are rejected. Access is limited to your own prepaid account and jobs.

Rotate a key by creating and deploying a replacement, then revoking the old key. Disabling a client account revokes all its keys; re-enabling it requires new keys.

Follow this integration flow

  1. Read GET /options for valid print settings and Indian state codes, and GET /account for your balance and approved file hostnames.
  2. Send an items array of book print settings to POST /quote to calculate each book and the complete printing total.
  3. Prepare the order with an items array containing every book and its final PDF URLs, one shipping_address, a unique external_reference, and max_total_minor set to your approved printing total.
  4. Persist a new Idempotency-Key with the complete order JSON before submitting it.
  5. Send POST /jobs. Save the returned job_id, which identifies the whole recipient order. All book entries and one combined printing debit are committed together.
  6. Use GET /jobs/{job_id} to read the order, each book’s production status, and the receipt state.

Quoting does not reserve funds or lock a price. Submission recalculates the price on the server. If the total exceeds your maximum, or your balance is insufficient, no job or debit is created.

API resources

Append these relative paths to the privately supplied POD_API_URL, without a trailing slash.

Method / pathResult
GET /accountYour prepaid balance in paise (balance_minor) and approved_file_hosts. The currency is always INR.
GET /optionsValid print codes, shipping_countries (IN), shipping_states (code-to-name map), and request limits.
POST /quoteCalculates each book’s price and the combined printing total. Returns an items array with unit_price_minor, total_minor, pages_rounded, and qty per book; top-level printing_total_minor and total_minor are the complete printing charge. Currency is always INR. It does not create an order or deduct money.
POST /jobsCreates one recipient order containing 1–20 books and a delivery address; requires JSON and an Idempotency-Key header.
GET /jobs/{job_id}Returns the status and receipt details for one of your submitted jobs.

Print settings for each book

Each object in items requires all eight fields below. Different books can use different print settings and quantities. Codes are strings; pages and qty are JSON integers. Query /options for the current accepted codes.

FieldAccepted values
size455: 4 x 5.5 in
410: 4 x 10 in (Manuscript)
457: 4.5 x 7 in
5585: 5.5 x 8.5 in
66: 6 x 6 in
6595: 6.5 x 9.5 in
8251175: 8.25 x 11.75 in
8511: 8.5 x 11 in
99: 9 x 9 in
9513: 9.5 x 13 in
1111: 11 x 11 in
paperML80: 80 GSM Maplitho
ML90: 90 GSM Maplitho
ML100: 100 GSM Maplitho
SM100: 100 GSM Matt Art Paper
SM130: 130 GSM Matt Art Paper
printBW: Black & White
4C: 4 Color
cover_print0: Single Side
1: Both Side
cover_lamMatt: Matt
Glossy: Glossy
bindingPUR: Paperback
HC: Hardcover
pagesInteger 1–5,000. Production rounding is returned as pages_rounded.
qtyInteger 1–10,000.

For colour printing (4C), select ML100, SM100, or SM130. The API rejects ML80 and ML90 for colour jobs.

Submit a job

Send Content-Type: application/json and an Idempotency-Key of 16–128 letters, numbers, underscores, or hyphens. A UUID is suitable. The JSON body limit is 64 KiB. Unknown fields are rejected.

Order fields

FieldRequirement
external_referenceRequired. Your unique order reference, 1–128 letters, numbers, dots, colons, underscores, or hyphens. Unique within your account.
itemsRequired. Array of 1–20 book objects. The combined quantity across all books must not exceed 10,000 copies. All books in one order are for the same recipient.
shipping_addressRequired. The recipient’s Indian delivery address, using the fields below. For another recipient, submit a separate order with a new reference and retry identifier.
max_total_minorRequired. Maximum combined printing charge in paise. For example, 50000 means ₹500.00. Normally copy total_minor from your multi-book quote. If printing costs more than this limit, the entire order is rejected without a charge. Shipping is settled separately.
dispatchOptional single-line delivery instructions, at most 1,000 UTF-8 bytes. These apply to the whole order.

Additional fields inside each book

FieldRequirement
titleRequired for submission; optional when quoting. Single-line book title, at most 200 UTF-8 bytes.
line_referenceOptional identifier unique within the order, 1–128 letters, numbers, dots, colons, underscores, or hyphens. Defaults to the book’s position: 1, 2, and so on.
book_urlsRequired for submission. Ordered array of 1–10 final print-ready PDF URLs for this book, each at most 4,096 bytes. HTTPS only, on an approved hostname. Do not send this field when quoting.
description, instructionsOptional single-line text for this book, at most 2,000 UTF-8 bytes each. Send these only when submitting.

Delivery address fields

Supply these inside shipping_address. Address and contact fields must be single-line strings; unknown fields are rejected.

FieldRequirement
nameRequired recipient name, at most 120 UTF-8 bytes.
companyOptional organisation name, at most 120 UTF-8 bytes.
address_1Required house/building, street and locality, at most 200 UTF-8 bytes.
address_2Optional additional address or landmark, at most 200 UTF-8 bytes.
cityRequired city, at most 100 UTF-8 bytes.
stateRequired state code from GET /options, such as MH for Maharashtra.
postcodeRequired six-digit Indian PIN code as a string.
countryRequired. Always IN. International delivery is not supported.
phoneRequired ten-digit Indian phone number, optionally prefixed with +91. Returned in +91 format.

Files are kept in the supplied order. The submission API records file references; it does not download, inspect, or prove that a URL contains a valid PDF. Provide file links that remain accessible for at least 48 hours after submission. Use your approved storage directly, without redirectors or URL shorteners.

Each book starts as Paid for printing. Shipping charges are still to be settled separately before dispatch. Clients cannot set the charge, account owner, payment state, printer order ID, or production status.

Request examples

The following shell examples read credentials and the private address from environment variables. Replace the illustrative PDF host with an approved hostname for your account.

Check your balance

curl --fail-with-body --silent --show-error \
  -H "X-POD-Key: $POD_API_KEY" \
  -H "Accept: application/json" \
  "$POD_API_URL/account"

Get a quote

Send each book’s settings and number of copies in items. This request is free and does not deduct your balance. Use the combined top-level total_minor as max_total_minor when submitting the whole order. Shipping is not included.

curl --fail-with-body --silent --show-error \
  -H "X-POD-Key: $POD_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"items":[
    {"line_reference":"book-1","title":"First book",
     "size":"5585","paper":"ML80","print":"BW",
     "cover_print":"1","cover_lam":"Matt","binding":"PUR",
     "pages":120,"qty":1},
    {"line_reference":"book-2","title":"Second book",
     "size":"5585","paper":"ML80","print":"BW",
     "cover_print":"1","cover_lam":"Matt","binding":"PUR",
     "pages":200,"qty":2}]}' \
  "$POD_API_URL/quote"

Prepare your job JSON

Save the following as job.json. The example maximum is illustrative; use the total from your actual quote.

{
  "external_reference": "YOUR-ORDER-0001",
  "shipping_address": {
    "name": "RECIPIENT NAME",
    "address_1": "HOUSE AND STREET",
    "address_2": "LOCALITY OR LANDMARK",
    "city": "Mumbai",
    "state": "MH",
    "postcode": "400004",
    "country": "IN",
    "phone": "+919876543210"
  },
  "items": [
    {
      "line_reference": "book-1",
      "title": "First book",
      "size": "5585", "paper": "ML80", "print": "BW",
      "cover_print": "1", "cover_lam": "Matt", "binding": "PUR",
      "pages": 120, "qty": 1,
      "book_urls": ["https://files.example.com/first-book.pdf"]
    },
    {
      "line_reference": "book-2",
      "title": "Second book",
      "size": "5585", "paper": "ML80", "print": "BW",
      "cover_print": "1", "cover_lam": "Matt", "binding": "PUR",
      "pages": 200, "qty": 2,
      "book_urls": ["https://files.example.com/second-book.pdf"]
    }
  ],
  "max_total_minor": 100000,
  "dispatch": "Pack all three copies together for this recipient."
}

Submit once

POD_IDEMPOTENCY_KEY is an environment variable containing a unique submission identifier that you generate and save for this job, such as a UUID. It is sent in the Idempotency-Key header so that a retry after a timeout cannot create a second job or charge. Use a new value for each new job; reuse the same value and unchanged job JSON when retrying that job. It is separate from your secret API key.

curl --fail-with-body --silent --show-error \
  --connect-timeout 10 --max-time 60 \
  -H "X-POD-Key: $POD_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $POD_IDEMPOTENCY_KEY" \
  --data-binary @job.json \
  "$POD_API_URL/jobs"

Understand the response

A newly accepted job returns HTTP 201 with replayed: false. If you retry an already accepted submission, the API returns HTTP 200 with replayed: true and the same job ID. This means your earlier submission succeeded; no additional job or charge was created. Both responses contain:

FieldMeaning
job_idShared identifier for the entire recipient order and all its books.
itemsEach book’s line_number, line_reference, title, qty, charged_minor, and production status.
shipping_addressThe saved delivery address for this order, visible only to your authenticated account and authorised staff.
external_reference, statusYour reference and the order’s production status, initially Paid. When books have different statuses, the order shows Partially processed; check each item’s status. When every book is Dispatched, the order also shows Dispatched.
currency, charged_minor, printing_total_minorINR and the combined printing debit in paise for every book.
shipping_total_minor, shipping_charge_statusnull and to_be_settled_separately. Shipping is not free or included in the prepaid printing deduction; our team settles it separately before dispatch.
balance_after_minorYour historical balance immediately after this job. Read /account for the latest balance.
notification_statuspending, sending, sent, or failed. Sent means the email transport accepted the receipt.
created_atUTC timestamp when the job was first accepted.
replayedfalse for a newly accepted job. true when a retry returns the existing job without another charge.

Retries and errors

Persist both your order reference and idempotency key before the first submission. If a timeout leaves the outcome unknown, retry the same JSON with the same identifiers. A replay does not create a second job or debit. A reference is unique per account even if a different idempotency key is sent.

Reusing either identifier with different job details returns 409 pod_idempotency_conflict. Do not silently change the files, quantity, title, or maximum price on a retry. Contact our team to resolve an accepted job before submitting a replacement.

HTTP statusAction
400Correct invalid JSON, fields, options, file hostnames, or missing identifiers. Errors include a readable message.
401Check your X-POD-Key. It may be missing, expired, or revoked.
402Insufficient prepaid funds. Arrange credit, then retry the unchanged request.
403HTTPS or account access is required. Contact our team if disabled.
404Job not found. Check the job ID returned by your submission.
409Resolve an identifier conflict, or obtain and approve a new quote if the price exceeds your maximum.
413 / 415Reduce the body to 64 KiB, or use application/json.
429Wait at least the Retry-After value. Limit: 60 requests per minute per account across all keys, and 300 per minute per source connection address.
503 / timeoutRetry the identical request and identifiers with exponential backoff and jitter. Do not generate a new order reference.
{"code":"pod_insufficient_balance",
 "message":"Insufficient prepaid balance. Ask Shrutgyan to add credit.",
 "data":{"status":402}}

Balances and submission receipts

The API uses the current Shrutgyan POD calculator for each book. All books, the recipient address, and one combined printing debit are stored together. If any book is invalid or the balance cannot cover the whole order, no book or debit is created. All keys for your account share one balance.

Shipping charges are confirmed and settled separately with our team before dispatch. The prepaid balance deduction and maximum-charge field cover printing only.

Once accepted, one receipt is sent to the client’s registered account email address. It lists every book, quantities, the combined printing charge, and the balance after submission. The delivery recipient is not automatically emailed. No API key, file URL, phone number, or full street address is included in the receipt. Submission acceptance does not confirm printing or dispatch.

If email fails, the job remains accepted and charged. Check notification_status or your account’s submission list; do not create another job to trigger an email. Our team can retry the receipt. Email delivery and spam filtering depend on your mail provider.

View recent submissions and balance transactions in My account → Print on demand. For cancellation or a billing correction, contact our team with the job ID. Cancellation and production edits do not automatically refund or reprice an accepted API job.

Newsletter

Get Jain learning ideas in your inbox

New products, activity guides and spiritual resources — delivered to your family.

No spam. Unsubscribe anytime.

Jainism For Kids

Learning Jainism made fun

Cash on Delivery

COD now available pan India

Shipping Wordwide

Spirituality home delivered

100% Secure Checkout

GPay / MasterCard / Visa / UPI