Integration guide

This guide covers how to manage value receipts programmatically and embed them in your application. For a conceptual overview of what value receipts are and how they work, see the overview.

Prerequisites

  • A Paid API key and the Paid SDK installed in the service that manages receipts.
  • Signals flowing and delivered value configured.
  • At least one customer with signal data in the date range you want to summarize.
  • For private or embedded receipts, embed authentication configured.

Creating and managing value receipts

Create a value receipt

Each call creates a receipt for the customer and date range you give it, from the delivered value available at that moment. Calling it twice with the same customer and dates gives you two receipts — that is how you report a period again with newer data.

POST /value-receipts/sync is deprecated. It returns the receipt a customer already has for a date range instead of creating one. Use the create endpoint below.

You only need a customer and a time period. No orders or products are required.

Choosing the date range

The range has to have ended — a receipt reports a period the customer can check, so an end date in the future is rejected. If your clock runs a few minutes ahead of ours, an end date just past the current time is read as the moment your request arrives rather than refused, so “through the end of today” works without you having to subtract a safety margin.

A range with nothing delivered in it still produces a receipt, reporting zero. Send the range you want the customer to see.

from paid import Paid
client = Paid(token="YOUR_PAID_API_KEY")
result = client.value_receipts.create(
external_customer_id="acme_123",
start_date="2026-01-01T00:00:00Z",
end_date="2026-03-31T23:59:59Z",
)
print(result.id) # value receipt ID
print(result.status) # "draft" or "posted"
print(result.public_url) # share URL

You can optionally scope a value receipt to a product or an order (but not both). This narrows the receipt to delivered value from that specific product or order rather than all activity for the customer.

Scoped to a product:

result = client.value_receipts.create(
external_customer_id="acme_123",
start_date="2026-01-01T00:00:00Z",
end_date="2026-03-31T23:59:59Z",
product={"product_id": "prod_xyz", "currency": "USD"},
)

Scoped to an order:

result = client.value_receipts.create(
external_customer_id="acme_123",
start_date="2026-01-01T00:00:00Z",
end_date="2026-03-31T23:59:59Z",
order_id="ord_abc123",
)

List value receipts

List value receipts with pagination and optional filters.

# List all value receipts
receipts = client.value_receipts.list()
for vr in receipts.data:
print(f"{vr.customer_name}: {vr.total_delivered_value} ({vr.status})")
# Filter by customer
receipts = client.value_receipts.list(
external_customer_id="acme_123",
limit=10,
offset=0,
)
# Include archived receipts
receipts = client.value_receipts.list(archived="true")

Available filters: customerId, externalCustomerId, orderId, productId, archived.

Get by ID

Fetch a single value receipt including its publish state.

vr = client.value_receipts.get(id="vr_abc123")
print(vr.status) # "draft" or "posted"
print(vr.is_published) # True or False
print(vr.published_at) # timestamp or None
print(vr.publish_expires_at) # expiry timestamp or None

Refresh

Re-populate a draft value receipt with the latest signal and delivered value data. This is useful when new signals are still coming in and you want the receipt to reflect the most recent numbers. Sealed receipts cannot be refreshed.

result = client.value_receipts.refresh(id="vr_abc123")
print(result.status) # "draft"

Seal

Seal a value receipt to make it immutable. This transitions it from draft to posted status. Once sealed, a receipt cannot be refreshed or re-populated. It becomes a permanent snapshot.

client.value_receipts.seal(id="vr_abc123")

Publish and unpublish

Publishing makes a value receipt accessible to anyone with the link. Unpublishing reverts it to private (JWT-gated) access.

# Publish with no expiry (permanent until unpublished)
vr = client.value_receipts.publish(id="vr_abc123")
print(vr.public_url) # share this URL
# Publish with an expiry
vr = client.value_receipts.publish(
id="vr_abc123",
publish_expires_at="2026-06-30T23:59:59Z",
)
# Unpublish (revert to JWT-gated)
vr = client.value_receipts.unpublish(id="vr_abc123")

Archive and unarchive

Archiving soft-deletes a value receipt. It is hidden from list results by default but can be restored.

# Archive
client.value_receipts.archive(id="vr_abc123")
# Unarchive
client.value_receipts.unarchive(id="vr_abc123")