> ## Documentation Index
> Fetch the complete documentation index at: https://docs.x402.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Payment-Identifier (Idempotency)

> The payment-identifier extension enables idempotency for x402 payments, allowing clients to safely retry requests without duplicate payment processing.

The payment-identifier extension provides an idempotency mechanism for x402 payments. Clients can include a unique payment ID with their requests, and servers can use this ID to deduplicate payment processing - ensuring that retries with the same payment ID return cached responses without re-processing payments.

## Use Cases

* **Network failures**: Safely retry failed requests without duplicate payments
* **Client crashes**: Resume requests after restart using persisted payment IDs
* **Load balancing**: Same request can hit different servers with shared cache
* **Testing**: Replay requests during development without spending funds

## How It Works

1. Server advertises `payment-identifier` extension support in the `PaymentRequired` response
2. Client generates a unique payment ID and includes it in the `PaymentPayload`
3. Server caches responses keyed by payment ID (with configurable TTL)
4. Retry requests with the same payment ID return cached responses without re-processing payment

## Quickstart for Buyers (Clients)

<Tabs>
  <Tab title="TypeScript">
    ### Step 1: Generate a Payment ID

    Use the `generatePaymentId()` utility to create a unique identifier:

    ```typescript theme={null}
    import { generatePaymentId } from "@x402/extensions/payment-identifier";

    const paymentId = generatePaymentId();
    // Example: "pay_7d5d747be160e280504c099d984bcfe0"

    // Custom prefix
    const orderId = generatePaymentId("order_");
    // Example: "order_7d5d747be160e280504c099d984bcfe0"
    ```

    ### Step 2: Add Payment ID to Extensions

    Hook into the payment flow to add the payment ID before payload creation:

    ```typescript theme={null}
    import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
    import {
      appendPaymentIdentifierToExtensions,
      generatePaymentId,
    } from "@x402/extensions/payment-identifier";

    const client = new x402Client();
    // ... register schemes ...

    // Generate a unique payment ID for this logical request
    const paymentId = generatePaymentId();

    // Hook into payment flow to add the payment ID
    client.onBeforePaymentCreation(async ({ paymentRequired }) => {
      if (paymentRequired.extensions) {
        // Only appends if server declared the extension
        appendPaymentIdentifierToExtensions(paymentRequired.extensions, paymentId);
      }
    });

    const fetchWithPayment = wrapFetchWithPayment(fetch, client);

    // First request - payment is processed
    const response1 = await fetchWithPayment(url);

    // Retry with same payment ID - cached response returned (no payment)
    const response2 = await fetchWithPayment(url);
    ```
  </Tab>

  <Tab title="Python">
    ### Step 1: Generate a Payment ID

    Use the `generate_payment_id()` utility to create a unique identifier:

    ```python theme={null}
    from x402.extensions.payment_identifier import generate_payment_id

    payment_id = generate_payment_id()
    # Example: "pay_7d5d747be160e280504c099d984bcfe0"

    # Custom prefix
    order_id = generate_payment_id("order_")
    # Example: "order_7d5d747be160e280504c099d984bcfe0"
    ```

    ### Step 2: Add Payment ID to Extensions

    Hook into the payment flow to add the payment ID before payload creation:

    ```python theme={null}
    from x402 import x402Client
    from x402.extensions.payment_identifier import (
        append_payment_identifier_to_extensions,
        generate_payment_id,
    )
    from x402.http.clients import x402HttpxClient
    from x402.schemas import PaymentCreationContext

    client = x402Client()
    # ... register schemes ...

    # Generate a unique payment ID for this logical request
    payment_id = generate_payment_id()

    # Hook into payment flow to add the payment ID
    async def before_payment_creation(context: PaymentCreationContext) -> None:
        extensions = context.payment_required.extensions
        if extensions is not None:
            # Only appends if server declared the extension
            append_payment_identifier_to_extensions(extensions, payment_id)

    client.on_before_payment_creation(before_payment_creation)

    async with x402HttpxClient(client) as http:
        # First request - payment is processed
        response1 = await http.get(url)

        # Retry with same payment ID - cached response returned (no payment)
        response2 = await http.get(url)
    ```
  </Tab>

  <Tab title="Go">
    ### Step 1: Generate a Payment ID

    Use the `GeneratePaymentID()` utility to create a unique identifier:

    ```go theme={null}
    import "github.com/x402-foundation/x402/go/extensions/paymentidentifier"

    // Generate with default prefix "pay_"
    paymentID := paymentidentifier.GeneratePaymentID("")
    // Example: "pay_7d5d747be160e280504c099d984bcfe0"

    // Generate with custom prefix
    paymentID = paymentidentifier.GeneratePaymentID("order_")
    // Example: "order_7d5d747be160e280504c099d984bcfe0"
    ```

    ### Step 2: Add Payment ID to Extensions

    Hook into the payment flow to add the payment ID before payload creation:

    ```go theme={null}
    import (
        x402 "github.com/x402-foundation/x402/go"
        "github.com/x402-foundation/x402/go/extensions/paymentidentifier"
    )

    client := x402.Newx402Client()
    // ... register schemes ...

    // Generate a unique payment ID for this logical request
    paymentID := paymentidentifier.GeneratePaymentID("")

    // Hook into payment flow to add the payment ID
    client.OnBeforePaymentCreation(func(ctx x402.PaymentCreationContext) (*x402.BeforePaymentCreationHookResult, error) {
        if ctx.Extensions == nil {
            return nil, nil
        }

        // Only add if server declared the extension
        if ctx.Extensions[paymentidentifier.PAYMENT_IDENTIFIER] == nil {
            return nil, nil
        }

        err := paymentidentifier.AppendPaymentIdentifierToExtensions(ctx.Extensions, paymentID)
        if err != nil {
            return nil, err
        }

        return nil, nil
    })

    // First request - payment is processed
    response1, err := client.MakeRequest(url)

    // Retry with same payment ID - cached response returned (no payment)
    response2, err := client.MakeRequest(url)
    ```
  </Tab>
</Tabs>

### Best Practices

1. **Generate payment IDs at the logical request level**, not per retry
2. **Persist payment IDs** for long-running operations so they survive restarts
3. **Use descriptive prefixes** (e.g., `generatePaymentId("order_")`) to identify payment types
4. **Don't reuse payment IDs** across different logical requests

## Quickstart for Sellers (Servers)

<Tabs>
  <Tab title="TypeScript">
    ### Step 1: Advertise Extension Support

    Declare the payment-identifier extension in your route configuration:

    ```typescript theme={null}
    import {
      paymentMiddlewareFromHTTPServer,
      x402ResourceServer,
      x402HTTPResourceServer,
    } from "@x402/express";
    import {
      declarePaymentIdentifierExtension,
      PAYMENT_IDENTIFIER,
    } from "@x402/extensions/payment-identifier";

    const routes = {
      "GET /weather": {
        accepts: [
          {
            scheme: "exact",
            price: "$0.001",
            network: "eip155:84532",
            payTo: address,
          },
        ],
        extensions: {
          [PAYMENT_IDENTIFIER]: declarePaymentIdentifierExtension(false), // optional
        },
      },
    };
    ```

    **Optional vs Required:**

    ```typescript theme={null}
    // Payment ID is optional (clients can omit it)
    declarePaymentIdentifierExtension(false)

    // Payment ID is required (clients must provide it or receive 400 Bad Request)
    declarePaymentIdentifierExtension(true)
    ```

    ### Step 2: Cache Responses After Settlement

    Store responses after successful payment settlement:

    ```typescript theme={null}
    import { extractPaymentIdentifier } from "@x402/extensions/payment-identifier";

    // In-memory cache (use Redis in production)
    const idempotencyCache = new Map<string, { timestamp: number; response: unknown }>();
    const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour

    const resourceServer = new x402ResourceServer(facilitatorClient)
      .register("eip155:84532", new ExactEvmScheme())
      .onAfterSettle(async ({ paymentPayload }) => {
        const paymentId = extractPaymentIdentifier(paymentPayload);
        if (paymentId) {
          idempotencyCache.set(paymentId, {
            timestamp: Date.now(),
            response: { /* your response data */ },
          });
        }
      });
    ```

    ### Step 3: Check Cache Before Payment

    Use the `onProtectedRequest` hook to return cached responses and skip payment processing:

    ```typescript theme={null}
    const httpServer = new x402HTTPResourceServer(resourceServer, routes)
      .onProtectedRequest(async (context) => {
        if (!context.paymentHeader) return;

        try {
          const paymentPayload = JSON.parse(
            Buffer.from(context.paymentHeader, "base64").toString("utf-8"),
          );
          const paymentId = extractPaymentIdentifier(paymentPayload);

          if (paymentId) {
            const cached = idempotencyCache.get(paymentId);
            if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
              return { grantAccess: true }; // Skip payment, serve from cache
            }
          }
        } catch {
          // Invalid payment header, continue to normal payment flow
        }
      });
    ```
  </Tab>

  <Tab title="Python">
    ### Step 1: Advertise Extension Support

    Declare the payment-identifier extension in your route configuration:

    ```python theme={null}
    from x402.server import x402ResourceServer
    from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption
    from x402.http.middleware.fastapi import PaymentMiddlewareASGI
    from x402.http.types import RouteConfig
    from x402.mechanisms.evm.exact import ExactEvmServerScheme
    from x402.extensions.payment_identifier import (
        declare_payment_identifier_extension,
        PAYMENT_IDENTIFIER,
    )

    routes = {
        "GET /weather": RouteConfig(
            accepts=[
                PaymentOption(
                    scheme="exact",
                    price="$0.001",
                    network="eip155:84532",
                    pay_to=address,
                ),
            ],
            extensions={
                PAYMENT_IDENTIFIER: declare_payment_identifier_extension(required=False),  # optional
            },
        ),
    }
    ```

    **Optional vs Required:**

    ```python theme={null}
    # Payment ID is optional (clients can omit it)
    declare_payment_identifier_extension(required=False)

    # Payment ID is required (clients must provide it or receive 400 Bad Request)
    declare_payment_identifier_extension(required=True)
    ```

    ### Step 2: Cache Responses After Settlement

    Store responses after successful payment settlement:

    ```python theme={null}
    import time
    from x402.schemas import SettleContext
    from x402.extensions.payment_identifier import extract_payment_identifier

    # In-memory cache (use Redis in production)
    idempotency_cache: dict = {}
    CACHE_TTL_SECONDS = 60 * 60  # 1 hour

    async def after_settle(ctx: SettleContext) -> None:
        payment_id = extract_payment_identifier(ctx.payment_payload)
        if payment_id:
            idempotency_cache[payment_id] = {
                "timestamp": time.time(),
                "response": {},  # your response data
            }

    server = x402ResourceServer(facilitator)
    server.register("eip155:84532", ExactEvmServerScheme())
    server.on_after_settle(after_settle)
    ```

    ### Step 3: Check Cache Before Payment

    Use FastAPI middleware to check the cache before the payment middleware processes the request:

    ```python theme={null}
    import base64
    import json
    from fastapi import Request, Response
    from x402.schemas import PaymentPayload

    @app.middleware("http")
    async def idempotency_middleware(request: Request, call_next):
        payment_header = request.headers.get("X-Payment")
        if payment_header:
            try:
                payment_data = json.loads(base64.b64decode(payment_header))
                payment_payload = PaymentPayload.model_validate(payment_data)
                payment_id = extract_payment_identifier(payment_payload)

                if payment_id:
                    cached = idempotency_cache.get(payment_id)
                    if cached and time.time() - cached["timestamp"] < CACHE_TTL_SECONDS:
                        return Response(
                            content=json.dumps(cached["response"]),
                            media_type="application/json",
                        )
            except Exception:
                pass  # Invalid payment header, continue to normal flow

        return await call_next(request)

    # Add payment middleware AFTER idempotency middleware
    app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
    ```
  </Tab>

  <Tab title="Go">
    ### Step 1: Advertise Extension Support

    Declare the payment-identifier extension in your route configuration:

    ```go theme={null}
    import (
        x402http "github.com/x402-foundation/x402/go/http"
        "github.com/x402-foundation/x402/go/extensions/paymentidentifier"
    )

    // Optional or required payment identifier (pick one)
    paymentIdExtension := paymentidentifier.DeclarePaymentIdentifierExtension(false) // optional
    // paymentIdExtension = paymentidentifier.DeclarePaymentIdentifierExtension(true) // required

    routes := x402http.RoutesConfig{
        "GET /weather": {
            Accepts: []x402http.PaymentOption{
                {
                    Scheme:  "exact",
                    Price:   "$0.001",
                    Network: "eip155:84532",
                    PayTo:   address,
                },
            },
            Extensions: map[string]interface{}{
                paymentidentifier.PAYMENT_IDENTIFIER: paymentIdExtension,
            },
        },
    }
    ```

    ### Step 2: Extract Payment ID

    Use the `ExtractPaymentIdentifier()` utility to get the payment ID from the payload:

    ```go theme={null}
    import "github.com/x402-foundation/x402/go/extensions/paymentidentifier"

    // In your handler
    payload := c.MustGet("x402_payload").(x402.PaymentPayload)

    paymentID, err := paymentidentifier.ExtractPaymentIdentifier(payload, true)
    if err != nil {
        // Handle invalid payment ID
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }

    // Check for duplicate
    if existingResponse, found := processedPayments[paymentID]; found {
        // Return cached response
        c.JSON(200, existingResponse)
        return
    }
    ```

    ### Step 3: Cache Responses

    Store responses after successful payment processing:

    ```go theme={null}
    // In-memory cache (use Redis in production)
    var processedPayments = make(map[string]interface{})

    // After processing payment
    processedPayments[paymentID] = responseData
    ```
  </Tab>
</Tabs>

### Idempotency Behavior

| Scenario                     | Server Response                          |
| ---------------------------- | ---------------------------------------- |
| New payment ID               | Process payment normally, cache response |
| Same payment ID (within TTL) | Return cached response, skip payment     |
| Same payment ID (after TTL)  | Process payment normally, update cache   |
| No payment ID                | Process payment normally (no caching)    |

### Configuration Options

#### Cache TTL

Adjust `CACHE_TTL_MS` (TypeScript/Go) or `CACHE_TTL_SECONDS` (Python) based on your use case:

* Short TTL (5-15 min): For time-sensitive resources
* Long TTL (1-24 hours): For static or infrequently changing resources

### Production Considerations

1. **Use Redis or similar** instead of in-memory cache for distributed systems
2. **Handle cache failures gracefully** - if cache is unavailable, process payment normally
3. **Consider payload hashing** - for additional safety, hash the full payload and reject if same ID but different payload (409 Conflict)
4. **Monitor cache hit rates** to tune TTL and detect abuse

## API Reference

<Tabs>
  <Tab title="TypeScript">
    ### Client Functions

    #### `generatePaymentId(prefix?)`

    Generates a cryptographically secure unique payment identifier.

    ```typescript theme={null}
    import { generatePaymentId } from "@x402/extensions/payment-identifier";

    const paymentId = generatePaymentId();
    // Returns: "pay_<32-character-hex-string>"

    const orderId = generatePaymentId("order_");
    // Returns: "order_<32-character-hex-string>"
    ```

    #### `appendPaymentIdentifierToExtensions(extensions, id?)`

    Adds a payment identifier to the extensions object. Only modifies extensions if the server declared support for the extension. If no payment ID is provided, one is generated automatically.

    ```typescript theme={null}
    import { appendPaymentIdentifierToExtensions } from "@x402/extensions/payment-identifier";

    const extensions = paymentRequired.extensions ?? {};
    appendPaymentIdentifierToExtensions(extensions, "pay_custom_id_1234567890abcdef");
    // extensions now contains the payment-identifier extension (only if server declared it)
    ```

    #### `isValidPaymentId(id)`

    Validates a payment identifier format.

    ```typescript theme={null}
    import { isValidPaymentId } from "@x402/extensions/payment-identifier";

    isValidPaymentId("pay_7d5d747be160e280504c099d984bcfe0"); // true
    isValidPaymentId("invalid"); // false (too short)
    ```

    ### Server Functions

    #### `declarePaymentIdentifierExtension(required?)`

    Creates a payment-identifier extension declaration for resource servers.

    ```typescript theme={null}
    import { declarePaymentIdentifierExtension } from "@x402/extensions/payment-identifier";

    // Optional payment ID (default)
    const extension = declarePaymentIdentifierExtension();

    // Required payment ID
    const extensionRequired = declarePaymentIdentifierExtension(true);
    ```

    #### `extractPaymentIdentifier(paymentPayload)`

    Extracts the payment identifier from a payment payload.

    ```typescript theme={null}
    import { extractPaymentIdentifier } from "@x402/extensions/payment-identifier";

    const paymentId = extractPaymentIdentifier(paymentPayload);
    if (paymentId) {
      // Check cache, implement idempotency logic
    }
    ```

    #### `validatePaymentIdentifier(extension)`

    Validates the payment identifier extension object structure and ID format.

    ```typescript theme={null}
    import { validatePaymentIdentifier } from "@x402/extensions/payment-identifier";

    const extension = paymentPayload.extensions?.["payment-identifier"];
    const result = validatePaymentIdentifier(extension);
    if (!result.valid) {
      console.error(result.errors);
    }
    ```

    ### Constants

    ```typescript theme={null}
    import {
      PAYMENT_IDENTIFIER,      // "payment-identifier"
      PAYMENT_ID_MIN_LENGTH,   // 16
      PAYMENT_ID_MAX_LENGTH,   // 128
      PAYMENT_ID_PATTERN,      // /^[a-zA-Z0-9_-]+$/
    } from "@x402/extensions/payment-identifier";
    ```
  </Tab>

  <Tab title="Python">
    ### Client Functions

    #### `generate_payment_id(prefix="pay_")`

    Generates a cryptographically secure unique payment identifier.

    ```python theme={null}
    from x402.extensions.payment_identifier import generate_payment_id

    payment_id = generate_payment_id()
    # Returns: "pay_<32-character-hex-string>"

    order_id = generate_payment_id("order_")
    # Returns: "order_<32-character-hex-string>"
    ```

    #### `append_payment_identifier_to_extensions(extensions, id=None)`

    Adds a payment identifier to the extensions object. Only modifies extensions if the server declared support for the extension. If no payment ID is provided, one is generated automatically.

    ```python theme={null}
    from x402.extensions.payment_identifier import append_payment_identifier_to_extensions

    extensions = payment_required.extensions or {}
    append_payment_identifier_to_extensions(extensions, "pay_custom_id_1234567890abcdef")
    # extensions now contains the payment-identifier extension (only if server declared it)
    ```

    #### `is_valid_payment_id(id)`

    Validates a payment identifier format.

    ```python theme={null}
    from x402.extensions.payment_identifier import is_valid_payment_id

    is_valid_payment_id("pay_7d5d747be160e280504c099d984bcfe0")  # True
    is_valid_payment_id("invalid")  # False (too short)
    ```

    ### Server Functions

    #### `declare_payment_identifier_extension(required=False)`

    Creates a payment-identifier extension declaration for resource servers.

    ```python theme={null}
    from x402.extensions.payment_identifier import declare_payment_identifier_extension

    # Optional payment ID (default)
    extension = declare_payment_identifier_extension()

    # Required payment ID
    extension_required = declare_payment_identifier_extension(required=True)
    ```

    #### `extract_payment_identifier(payment_payload)`

    Extracts the payment identifier from a payment payload.

    ```python theme={null}
    from x402.extensions.payment_identifier import extract_payment_identifier

    payment_id = extract_payment_identifier(payment_payload)
    if payment_id:
        # Check cache, implement idempotency logic
        pass
    ```

    #### `validate_payment_identifier(extension)`

    Validates the payment identifier extension object structure and ID format.

    ```python theme={null}
    from x402.extensions.payment_identifier import validate_payment_identifier

    extension = payment_payload.extensions.get("payment-identifier")
    result = validate_payment_identifier(extension)
    if not result.valid:
        print(result.errors)
    ```

    ### Constants

    ```python theme={null}
    from x402.extensions.payment_identifier import (
        PAYMENT_IDENTIFIER,      # "payment-identifier"
        PAYMENT_ID_MIN_LENGTH,   # 16
        PAYMENT_ID_MAX_LENGTH,   # 128
        PAYMENT_ID_PATTERN,      # re.compile(r"^[a-zA-Z0-9_-]+$")
    )
    ```
  </Tab>

  <Tab title="Go">
    ### Client Functions

    #### `GeneratePaymentID(prefix string)`

    Generates a cryptographically secure unique payment identifier.

    ```go theme={null}
    import "github.com/x402-foundation/x402/go/extensions/paymentidentifier"

    // Generate with default prefix "pay_"
    paymentID := paymentidentifier.GeneratePaymentID("")
    // Returns: "pay_<32-character-hex-string>"

    // Generate with custom prefix
    paymentID = paymentidentifier.GeneratePaymentID("order_")
    // Returns: "order_<32-character-hex-string>"
    ```

    #### `AppendPaymentIdentifierToExtensions(extensions map[string]interface{}, id string) error`

    Adds a payment identifier to the extensions object. Only modifies extensions if the server declared support for the extension. Pass an empty string to auto-generate an ID.

    ```go theme={null}
    import "github.com/x402-foundation/x402/go/extensions/paymentidentifier"

    extensions := make(map[string]interface{})
    err := paymentidentifier.AppendPaymentIdentifierToExtensions(extensions, "pay_custom_id_1234567890abcdef")
    // extensions now contains the payment-identifier extension (only if server declared it)
    ```

    #### `IsValidPaymentID(id string) bool`

    Validates a payment identifier format.

    ```go theme={null}
    import "github.com/x402-foundation/x402/go/extensions/paymentidentifier"

    valid := paymentidentifier.IsValidPaymentID("pay_7d5d747be160e280504c099d984bcfe0") // true
    valid = paymentidentifier.IsValidPaymentID("invalid") // false (too short)
    ```

    ### Server Functions

    #### `DeclarePaymentIdentifierExtension(required bool) PaymentIdentifierExtension`

    Creates a payment-identifier extension declaration for resource servers.

    ```go theme={null}
    import "github.com/x402-foundation/x402/go/extensions/paymentidentifier"

    // Optional payment ID
    extension := paymentidentifier.DeclarePaymentIdentifierExtension(false)

    // Required payment ID
    extensionRequired := paymentidentifier.DeclarePaymentIdentifierExtension(true)
    ```

    #### `ExtractPaymentIdentifier(payload PaymentPayload, validate bool) (string, error)`

    Extracts the payment identifier from a payment payload.

    ```go theme={null}
    import "github.com/x402-foundation/x402/go/extensions/paymentidentifier"

    paymentID, err := paymentidentifier.ExtractPaymentIdentifier(payload, true)
    if err != nil {
        // Handle error
    }
    if paymentID != "" {
        // Check cache, implement idempotency logic
    }
    ```

    #### `ValidatePaymentIdentifier(extension interface{}) ValidationResult`

    Validates the payment identifier extension object structure and ID format.

    ```go theme={null}
    import "github.com/x402-foundation/x402/go/extensions/paymentidentifier"

    extension := payload.Extensions[paymentidentifier.PAYMENT_IDENTIFIER]
    result := paymentidentifier.ValidatePaymentIdentifier(extension)
    if !result.Valid {
        // Handle validation errors
        fmt.Println(result.Errors)
    }
    ```

    ### Constants

    ```go theme={null}
    import "github.com/x402-foundation/x402/go/extensions/paymentidentifier"

    const (
        PAYMENT_IDENTIFIER    = "payment-identifier"
        PAYMENT_ID_MIN_LENGTH = 16
        PAYMENT_ID_MAX_LENGTH = 128
    )

    var PAYMENT_ID_PATTERN = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)
    ```
  </Tab>
</Tabs>

## Examples

Full working examples are available in the x402 repository:

**TypeScript:**

* [TypeScript Client Example](https://github.com/x402-foundation/x402/tree/main/examples/typescript/clients/payment-identifier)
* [TypeScript Server Example](https://github.com/x402-foundation/x402/tree/main/examples/typescript/servers/payment-identifier)

**Python:**

* [Python Client Example](https://github.com/x402-foundation/x402/tree/main/examples/python/clients/payment-identifier)
* [Python Server Example](https://github.com/x402-foundation/x402/tree/main/examples/python/servers/payment-identifier)

**Go:**

* [Go Client Example](https://github.com/x402-foundation/x402/tree/main/examples/go/clients/payment-identifier)
* [Go Server Example](https://github.com/x402-foundation/x402/tree/main/examples/go/servers/payment-identifier)

## FAQ

**Q: What happens if I reuse a payment ID for a different request?**
A: The server will return the cached response from the first request. Don't reuse payment IDs across different logical requests.

**Q: How long are payment IDs cached?**
A: This is configurable by the server. Typical TTLs range from 5 minutes to 24 hours depending on the use case.

**Q: Can I use custom payment ID formats?**
A: Payment IDs must be 16-128 characters, alphanumeric with hyphens and underscores allowed. Use `isValidPaymentId()` to validate custom IDs.

**Q: What if the server doesn't support payment-identifier?**
A: The extension is optional. If the server doesn't advertise support, clients can still make payments normally without idempotency.
