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

# Seamless Payment

> Program × Developer: let a Consumer pay for an order while Paylead delegates the payment to the payment method your Program already runs.

Seamless Payment lets a [Consumer](/glossary#consumer) pay for an order without leaving the environment they already trust. Paylead initiates the payment; your Program executes it with its own payment method and returns the result. Fewer checkout steps means a higher completion rate.

This page is for the **product and engineering teams** of a Program integrating as the payment delegation provider. It covers the Consumer experience, what you must build, and how the flow works both **in the Paylead WebApp** and **via API integration**.

<Info>
  **In progress.** Seamless Payment is being implemented on API version `2.0.0`. The contract below may still be adjusted through the API. Contact your Paylead operations manager for more details.
</Info>

## Roles

* **Paylead** owns the order, **generates the `payment_id`**, initiates the payment when the purchase is confirmed, completes the order on success, and handles any refunds (partial or total).
* **You (the Program)** receive the payment request on your endpoints, execute it with your payment method, return the result, and reconcile against your banking system.

<Info>
  **Identifiers.**

  * `payment_id`: a **UUID generated by Paylead**, matching the internal order (the generic term that covers both a WebApp purchase and a one-click API purchase). It is your **idempotency key**; echo it on every callback and, critically, in the wire reference (see Reconciliation).
  * `consumer_id`: Paylead's identifier for the user.
  * `account_id`: the account external\_id provided through the PM hub integration.
</Info>

## Two purchase modes, one payment contract

The delegated payment contract below is identical in both cases:

* **WebApp**: the Consumer completes a purchase inside the Paylead WebApp opened from your app.
* **API integration (coming)**: your app triggers a purchase through the Paylead API (one-click), without the WebApp.

## Consumer experience (WebApp)

1. The Consumer opens the WebApp from your app.
2. The Consumer selects what to buy and an amount, then confirms.
3. Paylead sends the payment request to your endpoint.
4. You authorize or reject the payment, synchronously or asynchronously.
5. On success, Paylead completes the order and redirects the Consumer to it.
6. On failure, Paylead shows an error and lets the Consumer retry.

## Authentication

<Warning>
  Both directions must be authenticated before go-live.

  * **Paylead to your endpoints:** Paylead authenticates its requests with the mechanism agreed for your Program (e.g. mTLS or a signed token). Reject unauthenticated calls.
  * **You to Paylead callbacks:** authenticate with the credentials Paylead issues for your Program. A `payment_id` alone must never be enough to trigger order completion.
</Warning>

## Delegated payment flow

A two-step process, plus an optional status endpoint.

### Step 1: Payment authorization (required)

When the purchase is confirmed, Paylead sends a `POST` to your authorization endpoint (URL configured per Program):

```json theme={null}
{
  "consumer_id": "bank-user-1234",
  "account_id": "acct-ext-5678",
  "payment_id": "9f2c1a44-6b7e-4c1d-9a2f-1e5c3b0a7d21",
  "amount": 1000
}
```

`amount` is in **minor units** (`1000` = `10.00`).

Respond with one of:

| HTTP  | Meaning                                                                  |
| ----- | ------------------------------------------------------------------------ |
| `201` | Accepted synchronously. Paylead completes the order immediately.         |
| `202` | Pending extra validation (e.g. SCA). You will send the result in Step 2. |
| `400` | Failed. Include a `failure_reason`.                                      |

`failure_reason` values (on `400` and in Step 2 failures):

* `INSUFFICIENT_FUNDS`
* `PAYMENT_LIMIT_EXCEEDED`
* `TECHNICAL_ISSUE`
* `USER_NOT_FOUND`

### Step 2: Payment result callback (asynchronous only)

If Step 1 returned `202`, notify Paylead once validation completes. Paylead provides the callback base URL for your Program. `payment_status` is a path segment: `success` or `failure`.

Success, empty JSON body:

```http theme={null}
POST {paylead_base_url}/consumers/{consumer_id}/payments/{payment_id}/success
Content-Type: application/json
{}
```

Failure:

```http theme={null}
POST {paylead_base_url}/consumers/{consumer_id}/payments/{payment_id}/failure
Content-Type: application/json
{ "failure_reason": "INSUFFICIENT_FUNDS" }
```

<Warning>
  **Resolve async payments in time.** With no callback within the finalization window, Paylead treats the payment as failed (`TECHNICAL_ISSUE`) and releases the order.
</Warning>

<Info>
  **Idempotency.** Paylead accepts one final result per `payment_id`; later callbacks on an already-resolved payment are rejected, and the callback is validated against the owning `consumer_id`.
</Info>

### Step 3: Status check (optional)

Expose an endpoint so Paylead can check a payment's outcome, for incident recovery and audit (URL to be confirmed per Program):

```http theme={null}
GET {program_base_url}/consumers/{consumer_id}/payments/{payment_id}
```

```json theme={null}
{
  "status": "success",
  "failure_reason": null
}
```

`status` is `success`, `failure`, or `pending`. `failure_reason` is `null` unless `status` is `failure`.

## Refunds

An order may be refunded, partially or in full. Paylead handles refunds.

## Reconciliation

Paylead reconciles each order with the payin it receives.

<Warning>
  You **MUST** include the `payment_id` in the **wire reference** of every bank transfer used to fund a purchase. It is the only key linking the order, the payment execution, the payin received, and any later refund. Without it, reconciliation and refunds are impossible.
</Warning>

## Error handling shown to the Consumer

On failure at Step 1 or Step 2, the WebApp shows:

> The payment could not be completed. No charge was made. You may try again with a different amount.

## Sequence diagram

```mermaid theme={null}
%%{init: {'themeVariables': {'actorBorder':'#0465ff','signalColor':'#378add'}}}%%
sequenceDiagram
    autonumber
    participant User as Consumer
    participant Webapp as Paylead WebApp
    participant PayleadBE as Paylead Backend
    participant PartnerBE as Your Backend (Payments)
    User->>Webapp: Selects what to buy and an amount, confirms
    Note over PayleadBE,PartnerBE: Delegated payment (endpoint provided by the Program)
    PayleadBE->>PartnerBE: POST authorization {consumer_id, account_id, payment_id, amount}
    alt Sync success (201)
        PartnerBE-->>PayleadBE: Accepted
        PayleadBE-->>Webapp: Complete order and redirect
    else Sync error (400)
        PartnerBE-->>PayleadBE: {failure_reason}
        Webapp-->>User: Payment error, option to retry
    else Async (202)
        PartnerBE-->>PayleadBE: Accepted, awaiting validation
        alt Async success
            PartnerBE->>PayleadBE: POST /payments/{payment_id}/success
            PayleadBE-->>Webapp: Complete order and redirect
        else Async failure
            PartnerBE->>PayleadBE: POST /payments/{payment_id}/failure {failure_reason}
            Webapp-->>User: Payment error, option to retry
        else No callback in time
            Note over PayleadBE: Finalization timeout, payment failed
            PayleadBE-->>Webapp: Payment error, option to retry
        end
    end
```

## Your responsibilities

**You must:**

* Authenticate Paylead's requests, and your own callbacks to Paylead.
* Expose the Step 1 authorization endpoint; respond `201`/`400` synchronously, or `202` then call Step 2.
* Resolve every `202` before the finalization window closes.
* Include `payment_id` in the wire reference of every funding transfer.
* Return documented, uppercase `failure_reason` values.

**You must not:**

* Approve or resolve the same `payment_id` more than once.
* Leave asynchronous transactions unresolved.

## What's next

<CardGroup cols={2}>
  <Card title="WebApp authentication" icon="key" href="/program/webapp/authentication">
    The SSO flow the Consumer goes through before reaching the purchase.
  </Card>

  <Card title="Manage Consumers" icon="user-cog" href="/program/user-journey/guides/manage-consumers">
    How you create Consumers and get the `consumer_id` and `account_id` used in the payment request.
  </Card>
</CardGroup>
