> For the complete documentation index, see [llms.txt](https://bify.gitbook.io/rwa-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bify.gitbook.io/rwa-docs/bify-sdk/end-to-end.md).

# End-to-End Integration

This is the complete BIFY Commerce flow for a partner-owned product order. The partner keeps ownership of the catalogue, price, inventory, cart, and fulfilment system. BIFY receives an order snapshot and operates the payment and digital-entitlement layer.

## Flow

1. The customer adds a product to the partner cart.
2. The partner backend calculates the order total in USDC base units.
3. The partner backend creates a BIFY checkout session.
4. The partner page mounts the BIFY browser component with the short-lived session credentials.
5. The customer enters contact and delivery details in the hosted checkout.
6. The customer sends the exact USDC amount to the displayed payment address on the displayed Base network.
7. The customer submits the transaction hash to BIFY.
8. BIFY verifies the canonical USDC contract, network, recipient, amount, reference, transaction success, and replay state.
9. BIFY settles the purchase and sends a signed `purchase.settled` event.
10. The partner reconciles the event and fulfils the physical order.
11. The customer supplies a recipient wallet when ready to mint the non-transferable certificate.
12. The customer signs the certificate transaction. BIFY confirms the receipt and sends `certificate.minted`.

Payment does not require a wallet connection on the partner website. A wallet is required only for an on-chain certificate or reward action.

## 1. Create the session on the partner backend

Keep the API key in the partner server process. Create the order snapshot from the partner's trusted cart and order database, not from browser-supplied price or inventory values.

```ts
// server/checkout.ts
import { BifyClient } from "@bify/sdk";

const bify = new BifyClient({
  apiKey: process.env.BIFY_API_KEY!,
  baseUrl: process.env.BIFY_API_BASE_URL, // Defaults to https://api.bify.io
  network: "base-sepolia",
});

export async function createBifySession(order: {
  id: string;
  productId: string;
  productName: string;
  category: string;
  quantity: number;
  totalUsdcBaseUnits: string;
}) {
  return bify.checkout.createOrderSession({
    externalOrderId: order.id,
    externalProductId: order.productId,
    productName: order.productName,
    productCategory: order.category,
    quantity: order.quantity,
    totalPriceUsdc: order.totalUsdcBaseUnits,
    shippingRequired: true,
    paymentMethod: "usdc",
    checkoutMode: "hosted_transfer",
    certificate: { enabled: true },
    idempotencyKey: `checkout:${order.id}`,
  });
}
```

`totalPriceUsdc` is an integer string in USDC base units. For six-decimal USDC, `25000000` represents `25 USDC`. The partner should calculate this value using decimal-safe arithmetic before calling the SDK.

The response includes `id`, `clientToken`, `expiresAt`, `network`, `chainId`, the USDC payment details, and the external order reference. The `clientToken` is intended for the browser checkout only and must not be stored as a long-lived credential.

## 2. Mount the hosted checkout

Render a container on the partner page and pass the session values returned by the partner backend.

```ts
// browser/checkout.ts
import { mountBifyHostedCheckout } from "@bify/commerce-widget";

const checkout = await mountBifyHostedCheckout({
  element: "#bify-checkout",
  apiBaseUrl: "https://api.bify.io",
  sessionId: window.checkoutSession.id,
  clientToken: window.checkoutSession.clientToken,
  theme: "light",
  themeToggle: true,
  onState: (state, message) => {
    // Use this for an accessible status region outside the widget if needed.
    console.info("BIFY checkout state", state, message);
  },
  onComplete: ({ session, transactionHash, certificate }) => {
    // The partner may show a receipt page. Fulfilment must still wait for
    // the signed server-side settlement event.
    console.log({ orderReference: session.externalOrderId, transactionHash });
    if (certificate.voucher && certificate.signature) {
      showCertificateClaim(certificate);
    }
  },
});

// Later, when the partner page is unmounted:
// checkout.destroy();
```

The widget validates the session, renders the details, delivery, and payment steps, displays the exact USDC amount and payment address, and submits only the client token and transaction hash to public BIFY routes.

## 3. Reconcile the server-side settlement

Use webhooks as the source of settlement notification. The browser callback is not an authorization to fulfil an order.

```ts
// server/webhooks/bify.ts
import { parseVerifiedWebhook } from "@bify/sdk";

export async function handleBifyWebhook(request: Request) {
  const rawBody = await request.text();
  const signature = request.headers.get("BIFY-Signature") ?? "";

  const event = parseVerifiedWebhook<{
    externalOrderId?: string;
    orderId?: string;
    purchaseId?: string;
    transactionHash?: string;
  }>({
    payload: rawBody,
    signature,
    secret: process.env.BIFY_WEBHOOK_SECRET,
  });

  // Store event.id before applying the state transition. A duplicate event
  // must return 2xx without fulfilling the order a second time.
  if (await alreadyProcessed(event.id)) return new Response(null, { status: 204 });

  switch (event.type) {
    case "purchase.settled":
      await markPaymentSettled(event.data);
      await beginPartnerFulfilment(event.data.externalOrderId!);
      break;
    case "certificate.minted":
      await markCertificateMinted(event.data);
      break;
    case "reward.claimed":
      await recordRewardClaim(event.data);
      break;
    default:
      await recordBifyEvent(event);
  }

  await markProcessed(event.id);
  return new Response(null, { status: 204 });
}
```

The signature must be checked against the untouched request body. Do not parse and re-serialize JSON before calling `parseVerifiedWebhook`.

## 4. Mark fulfilment

After the partner order system accepts the settled payment, mark fulfilment from the partner backend.

```ts
await bify.orders.markFulfilled({
  orderId: "bify_order_id",
  fulfilmentReference: "shipment_12345",
  idempotencyKey: "fulfilment:partner_order_123",
});
```

The fulfilment reference is an external operational reference. BIFY does not replace the partner's shipping or inventory system.

## 5. Customer certificate claim and mint

If the customer did not provide a wallet during checkout, the session remains settled while the certificate waits for a recipient wallet. The partner can show a claim page using the public client token.

```ts
// This call can be made from the certificate claim page. The client token
// must come from the active session and should not be treated as a user login.
const result = await fetch(
  `https://api.bify.io/v1/public/checkout/sessions/${encodeURIComponent(sessionId)}/claim`,
  {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      clientToken,
      walletAddress: recipientWallet,
    }),
  },
).then((response) => response.json());
```

The response contains a signed certificate voucher when the purchase is eligible. The browser can pass that voucher to `mountBifyCertificate` for the wallet transaction. The customer wallet must match the voucher buyer.

## Failure handling

| Situation                        | Partner behavior                                                                       |
| -------------------------------- | -------------------------------------------------------------------------------------- |
| Session expired                  | Create a new session with the same order reference and an appropriate idempotency key. |
| Payment not found                | Keep the order unpaid and ask the customer to check the hash and network.              |
| Payment pending                  | Do not fulfil until the server-side settlement event arrives.                          |
| Duplicate webhook                | Return 2xx after the existing event record is found.                                   |
| Certificate pending              | Keep the purchase settled and present the claim flow later.                            |
| Certificate confirmation delayed | Keep the certificate in a pending state and reconcile by transaction hash.             |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://bify.gitbook.io/rwa-docs/bify-sdk/end-to-end.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
