> This page is for version v2 (default).
> For other versions, use one of these documentation indexes:
> - v2 (default): https://docs.paid.ai/v-2/llms.txt
> - v1: https://docs.paid.ai/v-1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.paid.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.paid.ai/_mcp/server.

# Integration guide

> Create, manage, and embed value receipts using the Paid API and embed SDK

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](/documentation/value-receipts/overview).

## Prerequisites

* A [Paid API key](https://app.paid.ai/settings/api-keys) and the Paid SDK installed in the service that manages receipts.
* [Signals](/documentation/getting-started/first-signals) flowing and [delivered value](/documentation/getting-started/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](/documentation/value-receipts/authentication-and-embedding) 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.

> **Note**
>
> `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.

#### Python

```python
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.public_url)      # share URL
```

#### Node.js

```typescript
import { PaidClient } from "@paid-ai/paid-node";

const client = new PaidClient({ token: "YOUR_PAID_API_KEY" });

const result = await client.valueReceipts.create({
  externalCustomerId: "acme_123",
  startDate: "2026-01-01T00:00:00Z",
  endDate: "2026-03-31T23:59:59Z",
});

console.log(result.id);        // value receipt ID
console.log(result.publicUrl); // share URL
```

#### Go

```go
import (
    "fmt"

    paid "github.com/paid-ai/paid-go"
    paidclient "github.com/paid-ai/paid-go/client"
    "github.com/paid-ai/paid-go/option"
)

client := paidclient.NewClient(option.WithToken("YOUR_PAID_API_KEY"))

result, err := client.ValueReceipts.CreateValueReceipt(ctx, &paid.SyncValueReceiptRequest{
    ExternalCustomerID: paid.String("acme_123"),
    StartDate:          paid.MustParseDateTime("2026-01-01T00:00:00Z"),
    EndDate:            paid.MustParseDateTime("2026-03-31T23:59:59Z"),
})
if err != nil {
    return err
}

fmt.Println(result.ID)        // value receipt ID
fmt.Println(result.PublicURL) // 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:**

#### Python

```python
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"},
)
```

#### Node.js

```typescript
const result = await client.valueReceipts.create({
  externalCustomerId: "acme_123",
  startDate: "2026-01-01T00:00:00Z",
  endDate: "2026-03-31T23:59:59Z",
  product: { productId: "prod_xyz", currency: "USD" },
});
```

#### Go

```go
result, err := client.ValueReceipts.CreateValueReceipt(ctx, &paid.SyncValueReceiptRequest{
    ExternalCustomerID: paid.String("acme_123"),
    StartDate:          paid.MustParseDateTime("2026-01-01T00:00:00Z"),
    EndDate:            paid.MustParseDateTime("2026-03-31T23:59:59Z"),
    Product: &paid.SyncValueReceiptRequestProduct{
        ProductID: "prod_xyz",
        Currency:  paid.String("USD"),
    },
})
if err != nil {
    return err
}
fmt.Println(result.ID)
```

**Scoped to an order:**

#### Python

```python
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",
)
```

#### Node.js

```typescript
const result = await client.valueReceipts.create({
  externalCustomerId: "acme_123",
  startDate: "2026-01-01T00:00:00Z",
  endDate: "2026-03-31T23:59:59Z",
  orderId: "ord_abc123",
});
```

#### Go

```go
result, err := client.ValueReceipts.CreateValueReceipt(ctx, &paid.SyncValueReceiptRequest{
    ExternalCustomerID: paid.String("acme_123"),
    StartDate:          paid.MustParseDateTime("2026-01-01T00:00:00Z"),
    EndDate:            paid.MustParseDateTime("2026-03-31T23:59:59Z"),
    OrderID:            paid.String("ord_abc123"),
})
if err != nil {
    return err
}
fmt.Println(result.ID)
```

### List value receipts

List value receipts with pagination and optional filters.

#### Python

```python
# List all value receipts
receipts = client.value_receipts.list()

for vr in receipts.data:
    print(f"{vr.customer_name}: {vr.total_delivered_value}")

# 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")
```

#### Node.js

```typescript
// List all value receipts
const receipts = await client.valueReceipts.list();

for (const vr of receipts.data) {
  console.log(`${vr.customerName}: ${vr.totalDeliveredValue}`);
}

// Filter by customer
const filtered = await client.valueReceipts.list({
  externalCustomerId: "acme_123",
  limit: 10,
  offset: 0,
});

// Include archived receipts
const all = await client.valueReceipts.list({ archived: "true" });
```

#### Go

```go
// List all value receipts
receipts, err := client.ValueReceipts.ListValueReceipts(
    ctx,
    &paid.ListValueReceiptsRequest{},
)
if err != nil {
    return err
}

for _, vr := range receipts.Data {
    customerName := ""
    if vr.CustomerName != nil {
        customerName = *vr.CustomerName
    }
    fmt.Printf("%s: %v (%s)\n", customerName, vr.TotalDeliveredValue, vr.Status)
}

// Filter by customer
filtered, err := client.ValueReceipts.ListValueReceipts(
    ctx,
    &paid.ListValueReceiptsRequest{
        ExternalCustomerID: paid.String("acme_123"),
        Limit:              paid.Int(10),
        Offset:             paid.Int(0),
    },
)
if err != nil {
    return err
}
fmt.Println(filtered.Total)

// Include archived receipts
all, err := client.ValueReceipts.ListValueReceipts(
    ctx,
    &paid.ListValueReceiptsRequest{
        Archived: paid.ListValueReceiptsRequestArchivedTrue.Ptr(),
    },
)
if err != nil {
    return err
}
fmt.Println(all.Total)
```

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

### Get by ID

Fetch a single value receipt including its publish state.

#### Python

```python
vr = client.value_receipts.get(id="vr_abc123")

print(vr.is_published)       # True or False
print(vr.published_at)       # timestamp or None
print(vr.publish_expires_at) # expiry timestamp or None
```

#### Node.js

```typescript
const vr = await client.valueReceipts.get("vr_abc123");

console.log(vr.isPublished);      // true or false
console.log(vr.publishedAt);      // timestamp or null
console.log(vr.publishExpiresAt); // expiry timestamp or null
```

#### Go

```go
vr, err := client.ValueReceipts.GetValueReceiptByID(
    ctx,
    &paid.GetValueReceiptByIDRequest{ID: "vr_abc123"},
)
if err != nil {
    return err
}

fmt.Println(vr.IsPublished)      // true or false
fmt.Println(vr.PublishedAt)      // timestamp or nil
fmt.Println(vr.PublishExpiresAt) // expiry timestamp or nil
```

### Publish and unpublish

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

#### Python

```python
# 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")
```

#### Node.js

```typescript
// Publish with no expiry (permanent until unpublished)
const vr = await client.valueReceipts.publish("vr_abc123");
console.log(vr.publicUrl); // share this URL

// Publish with an expiry
const vrExpiring = await client.valueReceipts.publish("vr_abc123", {
  publishExpiresAt: "2026-06-30T23:59:59Z",
});

// Unpublish (revert to JWT-gated)
const vrPrivate = await client.valueReceipts.unpublish("vr_abc123");
```

#### Go

```go
// Publish with no expiry (permanent until unpublished)
vr, err := client.ValueReceipts.PublishValueReceipt(
    ctx,
    &paid.PublishValueReceiptBody{
        // ID is the path parameter; the SDK omits it from the JSON body.
        ID: "vr_abc123",
    },
)
if err != nil {
    return err
}
fmt.Println(vr.PublicURL) // share this URL

// Publish with an expiry
expiresAt := paid.MustParseDateTime("2026-06-30T23:59:59Z")
vrExpiring, err := client.ValueReceipts.PublishValueReceipt(
    ctx,
    &paid.PublishValueReceiptBody{
        // ID is the path parameter; PublishExpiresAt is the JSON body field.
        ID:               "vr_abc123",
        PublishExpiresAt: &expiresAt,
    },
)
if err != nil {
    return err
}
fmt.Println(vrExpiring.PublishExpiresAt)

// Unpublish (revert to JWT-gated)
vrPrivate, err := client.ValueReceipts.UnpublishValueReceipt(
    ctx,
    &paid.UnpublishValueReceiptRequest{ID: "vr_abc123"},
)
if err != nil {
    return err
}
fmt.Println(vrPrivate.IsPublished)
```

### Archive and unarchive

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

#### Python

```python
# Archive
client.value_receipts.archive(id="vr_abc123")

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

#### Node.js

```typescript
// Archive
await client.valueReceipts.archive("vr_abc123");

// Unarchive
await client.valueReceipts.unarchive("vr_abc123");
```

#### Go

```go
// Archive
_, err := client.ValueReceipts.ArchiveValueReceipt(
    ctx,
    &paid.ArchiveValueReceiptRequest{ID: "vr_abc123"},
)
if err != nil {
    return err
}

// Unarchive
_, err = client.ValueReceipts.UnarchiveValueReceipt(
    ctx,
    &paid.UnarchiveValueReceiptRequest{ID: "vr_abc123"},
)
if err != nil {
    return err
}
```