This specification defines the Digital Receipt Protocol (DRP), a standardized protocol for creating, transmitting, storing, and verifying digital receipts in commercial transactions. DRP provides a secure, privacy-preserving, and interoperable framework for merchants, consumers, payment processors, and third-party applications to exchange receipt data in a machine-readable format.
The protocol addresses the limitations of paper receipts and proprietary digital receipt systems by establishing common data formats, security mechanisms, discovery methods, and verification procedures that work across different vendors and platforms.
This document is an editor's draft and may be updated, replaced, or obsoleted at any time. It is inappropriate to cite this document as other than work in progress.
Traditional paper receipts present numerous challenges including environmental waste, consumer inconvenience, difficult expense tracking, and limited machine readability. While various digital receipt solutions exist, they lack interoperability and standardization, creating fragmented ecosystems where consumers must manage multiple apps and merchants must integrate with numerous proprietary systems.
The Digital Receipt Protocol aims to solve these problems by providing:
This specification covers:
This specification does not cover:
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
This specification defines the following conformance classes:
A DRP Receipt Provider must:
A DRP Receipt Consumer must:
The DRP data model is based on Schema.org vocabulary extended with DRP-specific properties.
The core entity is the Receipt which contains transaction details, merchant
information, line items, payment information, and metadata.
The Receipt object is the top-level container for all receipt data.
| Property | Type | Required | Description |
|---|---|---|---|
@context |
String or Array | Yes | JSON-LD context, MUST include DRP context URL |
@type |
String | Yes | MUST be "Receipt" |
receiptId |
String | Yes | Unique identifier for this receipt |
receiptNumber |
String | No | Human-readable receipt number |
dateIssued |
DateTime | Yes | ISO 8601 timestamp of transaction |
merchant |
Organization | Yes | Merchant information |
location |
Place | No | Physical location of transaction |
items |
Array[LineItem] | Yes | Items or services purchased |
totalPrice |
MonetaryAmount | Yes | Total amount paid |
subtotal |
MonetaryAmount | No | Subtotal before taxes and fees |
tax |
Array[TaxAmount] | No | Tax amounts applied |
discount |
Array[Discount] | No | Discounts applied |
tip |
MonetaryAmount | No | Gratuity amount |
paymentMethod |
PaymentMethod | Yes | Payment method used |
customer |
Person or Organization | No | Customer information (privacy-sensitive) |
metadata |
Object | No | Additional structured metadata |
signature |
DigitalSignature | Yes | Cryptographic signature |
Represents an individual item or service on the receipt.
| Property | Type | Required | Description |
|---|---|---|---|
@type |
String | Yes | MUST be "LineItem" |
name |
String | Yes | Item name or description |
sku |
String | No | Stock keeping unit identifier |
gtin |
String | No | Global Trade Item Number (barcode) |
quantity |
Number | Yes | Quantity purchased |
unitPrice |
MonetaryAmount | Yes | Price per unit |
totalPrice |
MonetaryAmount | Yes | Total price for this line item |
category |
String | No | Product category |
discount |
Array[Discount] | No | Discounts applied to this item |
tax |
Array[TaxAmount] | No | Taxes applied to this item |
warranty |
Warranty | No | Warranty information |
returnPolicy |
ReturnPolicy | No | Return policy for this item |
| Property | Type | Required | Description |
|---|---|---|---|
@type |
String | Yes | MUST be "Organization" |
name |
String | Yes | Legal business name |
taxId |
String | No | Tax identification number |
address |
PostalAddress | Yes | Business address |
telephone |
String | No | Contact phone number |
email |
String | No | Contact email address |
url |
URL | No | Merchant website |
logo |
URL or ImageObject | No | Merchant logo |
| Property | Type | Required | Description |
|---|---|---|---|
@type |
String | Yes | MUST be "MonetaryAmount" |
value |
Number | Yes | Numeric value |
currency |
String | Yes | ISO 4217 currency code |
| Property | Type | Required | Description |
|---|---|---|---|
@type |
String | Yes | "PaymentCard", "PaymentService", "Cash", etc. |
name |
String | No | Payment method name |
cardType |
String | No | Card brand (Visa, Mastercard, etc.) |
lastFourDigits |
String | No | Last 4 digits of card (if applicable) |
authorizationCode |
String | No | Payment authorization code |
transactionId |
String | No | Payment processor transaction ID |
| Property | Type | Required | Description |
|---|---|---|---|
@type |
String | Yes | MUST be "TaxAmount" |
name |
String | Yes | Tax name (e.g., "Sales Tax", "VAT") |
rate |
Number | No | Tax rate as percentage |
amount |
MonetaryAmount | Yes | Tax amount |
taxId |
String | No | Tax jurisdiction identifier |
| Property | Type | Required | Description |
|---|---|---|---|
@type |
String | Yes | MUST be "DigitalSignature" |
algorithm |
String | Yes | Signature algorithm (e.g., "RS256", "ES256") |
signatureValue |
String | Yes | Base64-encoded signature |
publicKey |
URL or String | Yes | Public key or key reference |
created |
DateTime | Yes | Signature creation timestamp |
nonce |
String | No | Unique value to prevent replay |
DRP receipts must be serialized as JSON-LD documents. The JSON-LD context must include:
"@context": [
"https://schema.org",
"https://www.w3.org/ns/drp/v1"
]
Example: Basic Digital Receipt
{
"@context": [
"https://schema.org",
"https://www.w3.org/ns/drp/v1"
],
"@type": "Receipt",
"receiptId": "urn:uuid:550e8400-e29b-41d4-a716-446655440000",
"receiptNumber": "TXN-2024-001234",
"dateIssued": "2024-12-04T14:32:00-06:00",
"merchant": {
"@type": "Organization",
"name": "Acme Electronics Store",
"taxId": "12-3456789",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Main Street",
"addressLocality": "Chicago",
"addressRegion": "IL",
"postalCode": "60601",
"addressCountry": "US"
},
"telephone": "+1-312-555-0100",
"email": "support@acmeelectronics.example",
"url": "https://acmeelectronics.example"
},
"location": {
"@type": "Place",
"name": "Acme Electronics - Downtown",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Main Street",
"addressLocality": "Chicago",
"addressRegion": "IL",
"postalCode": "60601",
"addressCountry": "US"
}
},
"items": [
{
"@type": "LineItem",
"name": "Wireless Bluetooth Headphones",
"sku": "WBH-2000-BLK",
"gtin": "00012345678905",
"quantity": 1,
"unitPrice": {
"@type": "MonetaryAmount",
"value": 79.99,
"currency": "USD"
},
"totalPrice": {
"@type": "MonetaryAmount",
"value": 79.99,
"currency": "USD"
},
"category": "Electronics > Audio > Headphones",
"warranty": {
"@type": "Warranty",
"duration": "P1Y",
"url": "https://acmeelectronics.example/warranty/WBH-2000"
}
},
{
"@type": "LineItem",
"name": "USB-C Cable (2m)",
"sku": "CBL-USBC-2M",
"gtin": "00012345678912",
"quantity": 2,
"unitPrice": {
"@type": "MonetaryAmount",
"value": 12.99,
"currency": "USD"
},
"totalPrice": {
"@type": "MonetaryAmount",
"value": 25.98,
"currency": "USD"
},
"category": "Electronics > Accessories > Cables"
}
],
"subtotal": {
"@type": "MonetaryAmount",
"value": 105.97,
"currency": "USD"
},
"tax": [
{
"@type": "TaxAmount",
"name": "Illinois Sales Tax",
"rate": 6.25,
"amount": {
"@type": "MonetaryAmount",
"value": 6.62,
"currency": "USD"
},
"taxId": "IL-SALES-TAX"
},
{
"@type": "TaxAmount",
"name": "Chicago Municipal Tax",
"rate": 1.25,
"amount": {
"@type": "MonetaryAmount",
"value": 1.32,
"currency": "USD"
},
"taxId": "CHI-MUNICIPAL-TAX"
}
],
"discount": [
{
"@type": "Discount",
"name": "Member Discount",
"code": "MEMBER10",
"amount": {
"@type": "MonetaryAmount",
"value": -10.60,
"currency": "USD"
}
}
],
"totalPrice": {
"@type": "MonetaryAmount",
"value": 103.31,
"currency": "USD"
},
"paymentMethod": {
"@type": "PaymentCard",
"name": "Credit Card",
"cardType": "Visa",
"lastFourDigits": "4321",
"authorizationCode": "AUTH123456",
"transactionId": "TXN-PROC-789012"
},
"metadata": {
"employeeId": "EMP-5678",
"registerId": "REG-03",
"receiptUrl": "https://receipts.acmeelectronics.example/550e8400-e29b-41d4-a716-446655440000"
},
"signature": {
"@type": "DigitalSignature",
"algorithm": "RS256",
"signatureValue": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"publicKey": "https://receipts.acmeelectronics.example/.well-known/jwks.json",
"created": "2024-12-04T14:32:05-06:00",
"nonce": "a3f2b1c9d8e7"
}
}
Implementations may extend the data model with additional properties for industry-specific needs. Extensions should use namespaced property names to avoid conflicts.
Example: Restaurant-specific extension
{
"@context": [
"https://schema.org",
"https://www.w3.org/ns/drp/v1",
{
"restaurant": "https://example.org/restaurant-extension#"
}
],
"@type": "Receipt",
"receiptId": "urn:uuid:123e4567-e89b-12d3-a456-426614174000",
"restaurant:tableNumber": "42",
"restaurant:serverName": "Jane Smith",
"restaurant:partySize": 4,
"tip": {
"@type": "MonetaryAmount",
"value": 15.00,
"currency": "USD"
}
}
Receipt discovery enables consumers to locate and retrieve digital receipts. DRP defines multiple discovery mechanisms to accommodate different use cases.
Merchants may provide QR codes containing receipt URLs.
The QR code must encode a URL in the following format:
https://receipts.example.com/r/{receiptId}?v=1&h={hash}
Where:
{receiptId}: Unique receipt identifierv: Protocol versionh: Optional integrity hash (SHA-256 of receipt data)Receipt providers may send receipts via email containing:
Example: HTML email with embedded receipt
<html>
<head>
<script type="application/ld+json">
{
"@context": ["https://schema.org", "https://www.w3.org/ns/drp/v1"],
"@type": "Receipt",
...
}
</script>
</head>
<body>
<h1>Your Receipt from Acme Electronics</h1>
<p><a href="https://receipts.acmeelectronics.example/550e8400">
View Digital Receipt
</a></p>
</body>
</html>
For NFC-enabled devices, merchants may provide NFC tags containing receipt URLs using NDEF format.
NDEF Record:
TNF: Well Known
Type: U (URI)
Payload: https://receipts.example.com/r/{receiptId}
Payment systems may include receipt endpoints in payment authorization responses, enabling automatic receipt delivery to consumer wallets.
Receipt providers should publish their receipt service metadata at:
https://example.com/.well-known/drp-config.json
Example: DRP Configuration
{
"version": "1.0",
"issuer": "https://receipts.acmeelectronics.example",
"receiptEndpoint": "https://receipts.acmeelectronics.example/api/receipts",
"jwksUri": "https://receipts.acmeelectronics.example/.well-known/jwks.json",
"supportedFormats": ["application/ld+json", "application/pdf"],
"features": ["digital-signature", "search", "archival"],
"privacyPolicy": "https://acmeelectronics.example/privacy",
"termsOfService": "https://acmeelectronics.example/terms"
}
Receipt providers must support HTTP GET requests to retrieve receipts.
GET /api/receipts/{receiptId} HTTP/1.1
Host: receipts.example.com
Accept: application/ld+json
Authorization: Bearer {access_token}
DRP-Version: 1.0
HTTP/1.1 200 OK
Content-Type: application/ld+json
Cache-Control: private, max-age=31536000
ETag: "550e8400-e29b-41d4-a716-446655440000-v1"
{
"@context": ["https://schema.org", "https://www.w3.org/ns/drp/v1"],
"@type": "Receipt",
...
}
| Header | Required | Description |
|---|---|---|
DRP-Version |
Yes | Protocol version (currently "1.0") |
Authorization |
Yes* | Bearer token for authenticated access |
Accept |
No | Preferred response format |
If-None-Match |
No | ETag for conditional requests |
*Required for non-public receipts
Receipt providers may support push delivery via webhooks.
POST /api/webhooks HTTP/1.1
Host: receipts.example.com
Content-Type: application/json
Authorization: Bearer {access_token}
{
"url": "https://consumer-app.example/webhooks/receipts",
"events": ["receipt.created", "receipt.updated"],
"secret": "webhook_secret_key"
}
POST /webhooks/receipts HTTP/1.1
Host: consumer-app.example
Content-Type: application/ld+json
X-DRP-Event: receipt.created
X-DRP-Signature: sha256=d8f2a1c3b4e5...
{
"@context": ["https://schema.org", "https://www.w3.org/ns/drp/v1"],
"@type": "Receipt",
...
}
Implementations may support batch receipt retrieval for efficiency.
POST /api/receipts/batch HTTP/1.1
Host: receipts.example.com
Content-Type: application/json
Authorization: Bearer {access_token}
{
"receiptIds": [
"550e8400-e29b-41d4-a716-446655440000",
"660e8400-e29b-41d4-a716-446655440001"
]
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"receipts": [
{ "@type": "Receipt", ... },
{ "@type": "Receipt", ... }
]
}
Receipt providers should support search capabilities.
GET /api/receipts?merchant=acme&from=2024-01-01&to=2024-12-31&minAmount=50 HTTP/1.1
Host: receipts.example.com
Authorization: Bearer {access_token}
HTTP/1.1 200 OK
Content-Type: application/json
{
"receipts": [...],
"totalResults": 42,
"nextPage": "https://receipts.example.com/api/receipts?page=2&..."
}
All receipts must be digitally signed by the issuing merchant or receipt provider. Signatures prevent tampering and enable verification of receipt authenticity.
Implementations must support at least one of:
signature fieldsignature object to the receiptExample: Signing pseudocode
// 1. Prepare receipt without signature
const receipt = {
"@context": [...],
"@type": "Receipt",
"receiptId": "...",
// ... other fields
};
// 2. Canonicalize
const canonical = canonicalize(receipt);
// 3. Hash
const hash = sha256(canonical);
// 4. Sign
const signature = sign(hash, privateKey, "RS256");
// 5. Encode
const signatureValue = base64encode(signature);
// 6. Add signature
receipt.signature = {
"@type": "DigitalSignature",
"algorithm": "RS256",
"signatureValue": signatureValue,
"publicKey": "https://receipts.example.com/.well-known/jwks.json",
"created": new Date().toISOString(),
"nonce": generateNonce()
};
signature object from the receiptsignature field from the receiptReceipt providers must publish public keys using JSON Web Key Set (JWKS) format at a well-known URL.
Example: JWKS endpoint
GET /.well-known/jwks.json HTTP/1.1
Host: receipts.example.com
HTTP/1.1 200 OK
Content-Type: application/json
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "2024-12-key-1",
"n": "xGOr-H7A-D...",
"e": "AQAB",
"alg": "RS256"
}
]
}
Receipt providers should rotate signing keys periodically (recommended: annually). Old public keys must remain available for historical receipt verification.
Receipt providers must minimize collection and
storage of personally identifiable information (PII). The customer
field should only be included when explicitly
requested or required for business purposes.
Receipt endpoints must implement authentication and authorization:
GET /api/receipts/550e8400-e29b-41d4-a716-446655440000 HTTP/1.1
Host: receipts.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Receipt providers should establish clear retention policies. Consumers must have the ability to:
All receipt transmissions must use TLS 1.2 or higher. Receipt endpoints must not accept unencrypted HTTP connections.
For analytics or aggregated reporting, receipt providers should anonymize data by:
Receipt providers operating in jurisdictions with data protection regulations must comply with applicable laws including:
| Status Code | Meaning | Usage |
|---|---|---|
| 200 OK | Success | Receipt retrieved successfully |
| 304 Not Modified | Cached | Receipt unchanged (ETag match) |
| 400 Bad Request | Invalid request | Malformed receipt ID or parameters |
| 401 Unauthorized | Not authenticated | Missing or invalid authentication |
| 403 Forbidden | Not authorized | Valid auth but insufficient permissions |
| 404 Not Found | Receipt not found | Receipt ID does not exist |
| 410 Gone | Deleted | Receipt was permanently deleted |
| 429 Too Many Requests | Rate limited | Too many requests in time window |
| 500 Internal Server Error | Server error | Unexpected server error |
| 503 Service Unavailable | Temporarily unavailable | Maintenance or overload |
Error responses should include a JSON body with details:
Example: Error response
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"code": "receipt_not_found",
"message": "Receipt with ID '550e8400-e29b-41d4-a716-446655440000' was not found",
"details": {
"receiptId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2024-12-04T14:32:00Z"
},
"documentationUrl": "https://docs.drp.example/errors/receipt_not_found"
}
}
For validation failures, include field-specific error details:
{
"error": {
"code": "validation_error",
"message": "Receipt validation failed",
"validationErrors": [
{
"field": "totalPrice.value",
"message": "Total price does not match sum of line items",
"expected": 103.31,
"actual": 100.00
},
{
"field": "signature.algorithm",
"message": "Unsupported signature algorithm",
"provided": "HS256",
"supported": ["RS256", "ES256", "PS256"]
}
]
}
}
Receipt text content should be provided in the
consumer's preferred language when available. Use the Accept-Language
HTTP header for language negotiation.
GET /api/receipts/550e8400 HTTP/1.1
Accept-Language: es-MX, es;q=0.9, en;q=0.8
Implementations may use JSON-LD language maps for multilingual content:
{
"@type": "LineItem",
"name": {
"@value": "Audífonos Bluetooth Inalámbricos",
"@language": "es"
},
"name": {
"@value": "Wireless Bluetooth Headphones",
"@language": "en"
}
}
All monetary amounts must include ISO 4217 currency codes. Display formatting should follow locale conventions but storage uses standardized decimal representation.
All timestamps must use ISO 8601 format with timezone information:
"dateIssued": "2024-12-04T14:32:00-06:00"
Receipt presentations (web views, apps, etc.) must conform to WCAG 2.1 Level AA guidelines:
Receipt providers should offer receipts in multiple formats:
GET /api/receipts/550e8400 HTTP/1.1
Accept: text/html
HTTP/1.1 200 OK
Content-Type: text/html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Receipt - Acme Electronics</title>
</head>
<body>
<main role="main">
<h1>Receipt</h1>
...
</main>
</body>
</html>
Implementations may add custom properties using namespaced names. Custom properties should use reverse domain notation or explicit context URLs.
{
"@context": [
"https://schema.org",
"https://www.w3.org/ns/drp/v1",
{
"acme": "https://acmeelectronics.example/receipt-extension#"
}
],
"acme:loyaltyPoints": 150,
"acme:rewardsProgram": "Gold Member"
}
Industry-specific extensions may define additional types and properties. Common extensions include:
This specification registers the following media type:
This specification registers the following well-known URI:
{
"@context": ["https://schema.org", "https://www.w3.org/ns/drp/v1"],
"@type": "Receipt",
"receiptId": "urn:uuid:789e4567-e89b-12d3-a456-426614174000",
"receiptNumber": "TABLE-42-2024-1204",
"dateIssued": "2024-12-04T19:45:00-06:00",
"merchant": {
"@type": "Restaurant",
"name": "The Blue Bistro",
"address": {
"@type": "PostalAddress",
"streetAddress": "456 Oak Avenue",
"addressLocality": "Chicago",
"addressRegion": "IL",
"postalCode": "60614",
"addressCountry": "US"
}
},
"items": [
{
"@type": "LineItem",
"name": "Caesar Salad",
"quantity": 2,
"unitPrice": {"@type": "MonetaryAmount", "value": 12.00, "currency": "USD"},
"totalPrice": {"@type": "MonetaryAmount", "value": 24.00, "currency": "USD"}
},
{
"@type": "LineItem",
"name": "Grilled Salmon",
"quantity": 1,
"unitPrice": {"@type": "MonetaryAmount", "value": 28.00, "currency": "USD"},
"totalPrice": {"@type": "MonetaryAmount", "value": 28.00, "currency": "USD"}
},
{
"@type": "LineItem",
"name": "House Wine (Glass)",
"quantity": 2,
"unitPrice": {"@type": "MonetaryAmount", "value": 9.00, "currency": "USD"},
"totalPrice": {"@type": "MonetaryAmount", "value": 18.00, "currency": "USD"}
}
],
"subtotal": {"@type": "MonetaryAmount", "value": 70.00, "currency": "USD"},
"tax": [{
"@type": "TaxAmount",
"name": "Sales Tax",
"rate": 10.25,
"amount": {"@type": "MonetaryAmount", "value": 7.18, "currency": "USD"}
}],
"tip": {"@type": "MonetaryAmount", "value": 14.00, "currency": "USD"},
"totalPrice": {"@type": "MonetaryAmount", "value": 91.18, "currency": "USD"},
"paymentMethod": {
"@type": "PaymentCard",
"cardType": "Mastercard",
"lastFourDigits": "5678"
},
"metadata": {
"tableNumber": "42",
"serverName": "Maria Garcia",
"partySize": 2
},
"signature": {
"@type": "DigitalSignature",
"algorithm": "RS256",
"signatureValue": "eyJhbGc...",
"publicKey": "https://receipts.bluebistro.example/.well-known/jwks.json",
"created": "2024-12-04T19:46:00-06:00"
}
}
{
"@context": ["https://schema.org", "https://www.w3.org/ns/drp/v1"],
"@type": "Receipt",
"receiptId": "urn:uuid:890e4567-e89b-12d3-a456-426614174000",
"receiptNumber": "SUB-2024-DEC-123456",
"dateIssued": "2024-12-01T00:00:00Z",
"merchant": {
"@type": "Organization",
"name": "StreamFlix Media Services",
"url": "https://streamflix.example"
},
"items": [{
"@type": "LineItem",
"name": "Premium Plan - Monthly Subscription",
"quantity": 1,
"unitPrice": {"@type": "MonetaryAmount", "value": 15.99, "currency": "USD"},
"totalPrice": {"@type": "MonetaryAmount", "value": 15.99, "currency": "USD"},
"metadata": {
"subscriptionId": "sub_1234567890",
"billingPeriod": "2024-12-01/2025-01-01",
"autoRenew": true,
"nextBillingDate": "2025-01-01"
}
}],
"totalPrice": {"@type": "MonetaryAmount", "value": 15.99, "currency": "USD"},
"paymentMethod": {
"@type": "PaymentCard",
"cardType": "Visa",
"lastFourDigits": "1234"
},
"signature": {
"@type": "DigitalSignature",
"algorithm": "ES256",
"signatureValue": "MEUCIQD...",
"publicKey": "https://api.streamflix.example/.well-known/jwks.json",
"created": "2024-12-01T00:00:05Z"
}
}
This specification builds upon work from the W3C Web Payments Working Group, Schema.org community, and various industry standards organizations. Special thanks to contributors from retail, hospitality, and technology sectors who provided real-world use cases and implementation feedback.