For developers
Web services integration
Your site keeps the catalogue, the cart and the customer. DMR issues the licence and the link. Three operations connect the two — over REST for new builds, over SOAP for the retailers already running on it.
How the integration is shaped
Publishers upload their masters to the Digital Media Reserve repository. Publishers and retailers then integrate with the reserve in order to sell or lend those files from their own website. Whichever transport you use, the reserve never sees your customer and you never see the encryption.
New integrations use the REST API — JSON over HTTPS, bearer-token authentication, the same three operations. SOAP remains supported for retailers already built on it; it is not deprecated and it is not going anywhere.
What your site needs
- A storefront that can call an API
- Any language, any framework. For REST, anything that can make an authenticated HTTPS request and read JSON.
- Somewhere server-side to keep credentials
- Your token, or your CommerceID, RetailerID and RetailerKey. Never in client-side code.
- A static IP
- For SOAP, your site must be bound to a static address, which we allow-list against your retailer account. REST accounts can be IP-restricted on request.
- Nothing else
- No platform migration, no change of payment gateway, and no rebuild of your catalogue pages.
Onboarding
Getting a retail site connected
Apply for a retailer account
On approval we issue your credentials — a bearer token for REST, or CommerceID, RetailerID and RetailerKey for SOAP.
Pull the catalogue
Export the metadata for available titles as XML, or point an ONIX feed at the reserve and let it stay in step by itself.
Build your product pages
Import that metadata so customers can find and buy from your own catalogue pages, in your own design.
Store credentials server-side
Credentials sign every call and never belong in client-side code.
Check availability in your add-to-cart flow
Confirm the item is available in the requested format before you ask anyone to pay.
Create the transaction after payment succeeds
Exchange your transaction ID for the download link, and present that link to your customer.
Reference
The three operations
The same three whichever transport you use. Each card shows the REST path first and the SOAP service name beneath it.
Availability
Given an item and a format, tells you whether it is available for sale or loan before you ask anyone to pay.POST /v1/availabilityCheckAvailability
Transaction
Given your own transaction ID, returns the protected download link for the fulfilled file.POST /v1/transactionsNewTransaction
Re-issue
Against the same transaction ID, re-issues the link — for a customer who lost the file or changed device.POST /v1/transactions/{{id}}/linkRegenerateDownloadLink
REST — check, then fulfil
POST /v1/transactions
Authorization: Bearer <retailer token>
Content-Type: application/json
{
"transaction_id": "your-order-4471",
"item_id": "dmr:9788195xxxxxx",
"format": "epub", // epub | pdfa | video
"protection": "acs", // acs | social
"recipient": {
"name": "A. Reader", // used by social DRM
"email": "reader@example.com"
}
}
200 OK
{
"transaction_id": "your-order-4471",
"download_url": "https://ā¦/fulfil/9f2cā¦",
"expires_at": "2026-09-13T11:04:00Z",
"protection": "acs"
}
409 Conflict
{
"error": {
"code": "DUPLICATE_TRANSID",
"message": "Duplicate transaction ID."
}
}
Error codes are shared with the SOAP services, so a retailer moving from one to the other keeps their existing error handling.
SOAP — the original services
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<NewTransactionResponse>
<Books><Book>
<DownloadLink>Download link for BookID</DownloadLink>
</Book></Books>
</NewTransactionResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
/* Hash your retailer credentials before every call. */
$stringpass = md5($commerceid) . $retailerid . $bookid . $format . $transid;
$password = hash_hmac("sha1", $stringpass, $retailerkey);
$client->addHeader(array('Username', md5($commerceid), $_NS));
$client->addHeader(array('Password', $password, $_NS));
$result = $client->call('NewTransaction', array(
'RetailerID' => $retailerid,
'TransID' => $transid,
'BookID' => $bookid,
'Format' => $format
), $options);
Endpoint /webservices/retailers/. Reference implementation uses PEAR-SOAP 0.12.0; any SOAP client that can set envelope headers will do.
About this reference
The REST paths and payloads shown above illustrate the shape of the API so you can judge the integration effort before you commit to it. The authoritative reference — with the full schema, rate limits and sandbox credentials — is issued with your retailer account. The SOAP services are documented exactly as they run today.
Catalogue
ONIX catalogue sync
Nobody should be re-typing a subtitle into three systems. Send us ONIX for Books and your catalogue in the reserve keeps itself current — titles, contributors, subjects, prices, rights territories and availability.
Publishers who already generate ONIX for their distributors can point the same feed at the reserve. Publishers who do not can have it built — OnixMaster is the group's own ONIX application, and it comes with an e-commerce web-store that the reserve can fulfil protected files behind.
- Scheduled or on-demand
- Drop a feed on a schedule, or push an update when a title changes.
- New titles appear without re-keying
- A record added to your feed becomes a catalogue entry in the reserve.
- Descriptive data carried through
- Title, contributors, subjects, product form and prices come across as they stand in your ONIX.
- Retailers pull it back out
- Your integrated retailers export catalogue metadata as XML and build their product pages from it.
Parameters
These are the SOAP parameters. All six are mandatory on every call that uses them. TransID — transaction_id in REST — is yours to choose and yours to keep: it is the only handle you have for regenerating a link later.
| Name | Description |
|---|---|
| Username | Identifies the retailer. Pass the MD5 hash of the CommerceID issued by Digital Media Reserve. |
| Password | A SHA-1 HMAC used to validate the integrity of the calling retailer. |
| RetailerID | The unique retailer ID assigned to your account. |
| TransID | Your own unique transaction ID. Used to regenerate a download link in future. |
| BookID | The identifier Digital Media Reserve holds for each eBook. |
| Format | EPUB or PDF/A. |
Error codes
Shared between both transports. In SOAP they arrive inside the envelope as a code and a message; in REST as an error object with the same code. Map them once and your support desk never has to read XML.
| Code | Meaning | What to do |
|---|---|---|
| INVALID_SOAP_REQUEST | Invalid SOAP request, got nothing. | Check the endpoint and that a body was sent. |
| INVALID_SOAP_MESSAGE | Invalid SOAP message. | Validate the envelope against the samples above. |
| INVALID_HEADER | A header parameter is blank. | Confirm Username and Password are both set. |
| MISSING_PARAMETER | The request is missing a service parameter. | All listed parameters are mandatory. |
| INVALID_USERNAME | Invalid input parameter: Username. | Username must be the MD5 of your CommerceID. |
| INVALID_PASSWORD | Invalid input parameter: Password. | Re-check the HMAC string order and your retailer key. |
| ACNT_NOT_APPROVED | Account approval is pending. | Contact your DMR account manager. |
| ACNT_BLOCKED | The account has been blocked. | Contact accounts@dmi.systems. |
| RETAIL_ACNT_NOT_APPROVED | The retail account is pending. | Approval is per retailer, not per organisation. |
| RETAIL_ACNT_BLOCKED | The retail account has been blocked. | Contact accounts@dmi.systems. |
| INVALID_RETAILER_ID | Invalid retailer ID. | Check the RetailerID against the credentials issued to you. |
| DUPLICATE_TRANSID | Duplicate transaction ID. | Use RegenerateDownloadLink instead of NewTransaction. |
| NOT_AVAILABLE_FOR_PURCHASE | The eBook is not available for purchase. | Call CheckAvailability before taking payment. |
| ERROR_IN_LINK_GENERATION | Error in link generation. | Retry; if it persists, raise it with tech support. |
| TRANSID_NOT_EXISTS | The transaction ID does not exist. | Only transactions created via NewTransaction can be regenerated. |
| INTERNAL_ERROR | The system is unable to process your request. | Retry after a short interval. |
Video integration
The video reserve uses a token-based REST flow rather than SOAP: your backend requests a one-time playback token (OTP) for a given video and viewer, and your page or app hands that token to the player. Watermark text, device policy and geography rules are set per token. Full video API notes are issued with your account.
Want the full manual?
The complete Retailer DRM Web Services manual — syntax, request and response samples, PHP reference code and the error table — is issued under NDA with your retailer account.