<!-- Source: https://docs.paxeer.app/payments-quickstart/ -->

# Your first payment

Quote, commit, and verify a Paxeer X payment using the application SDK or a native Asset transfer.

## Choose your integration

Use the application SDK when you want account-level payment journeys and bearer-token authentication. Use the native CLI when you control a signing identity and need explicit canonical activities, receipt policy, fee limits, and commitment selection. The LayerX package and command names are the integration interfaces of Paxeer X.

## 1. Install the application packages

```
npm install @sidiora/layerx-sdk @sidiora/layerx-buyer-middleware
```

Configure `LAYERX_API_URL` with your environment's API base URL and `LAYERX_API_TOKEN` with its account bearer token. Use HTTPS outside a loopback emulator. These credentials identify your API account; do not embed them in browser bundles or logs.

## 2. Quote and commit the payment

This SDK integration accepts your typed source, destination, and money values. Choose `paymentKey` from a persistent order identifier or request digest and retain it before committing.

```
import { LayerXPaymentHttpTransport } from "@sidiora/layerx-buyer-middleware";
import { ProductionClient, SecretBytes, idempotencyKey } from "@sidiora/layerx-sdk";

export const openLayerX = (apiUrl, apiToken) => new ProductionClient(
  new LayerXPaymentHttpTransport({
    baseUrl: apiUrl,
    bearerToken: new SecretBytes(new TextEncoder().encode(apiToken))
  })
);

export const pay = async (layerx, source, destination, money, paymentKey) => {
  const quote = await layerx.human("move.quote", { source, destination, money });
  return layerx.human(
    "move.commit",
    { quote_id: quote.quote_id },
    { idempotencyKey: idempotencyKey(paymentKey) }
  );
};
```

The quote establishes the payment terms, mechanism, fee ceiling, arrival expectation, and irreversible legs. Present these terms for approval before committing. An expired quote must be refreshed and approved again. Monetary quantities use integer base units rather than floating-point arithmetic.

## 3. Follow the original journey

Store the returned journey identifier alongside the purchase key. Read its progress through `journey.get` and resolve evidence references through `evidence.get`. A `layerx-receipt` reference identifies canonical receipt evidence. Finish only when the journey reaches `done` or `done-finalised` with verified evidence.

| Observed outcome | Next action |
| --- | --- |
| `waiting-for-you` | Obtain the requested decision before expiry. |
| `still-checking` | Track the existing journey; lock controls that could create a duplicate payment. |
| `refused` | Read refusal authority and `money_left`. |
| `done` / `done-finalised` | Verify evidence and record the settlement before fulfilment. |

## Native path: prepare a funded identity

The CLI uses your local key, a stored gateway credential, and a receipt policy supplied independently of the RPC response you verify. A policy binds protocol version, network, sequencer identity and key, permitted batches, and checkpoint context. Keep private seeds out of shell history.

```
cargo build --manifest-path platform/cli/Cargo.toml
export PATH="$PWD/platform/target/debug:$PATH"
layerx key create alice
layerx key default alice
layerx wallet list

export RPC_URL=https://api-mainnet-beta.paxeer.network/rpc
export RECEIPT_POLICY=/absolute/path/to/receipt-policy.json
export FEE_LIMIT='<maximum fee in base units>'
export ASSET_ID='<64-hex Asset id>'
export RECIPIENT_DID='<recipient DID>'
```

The OS keyring stores keys by default; headless environments use the configured encrypted file store. Fund the payer through a custody credit backed by a deposit to custody precompile `0x0000000000000000000000000000000000001013` on Paxeer chain `125`. The signed funding activity binds deposit evidence to the beneficiary; its deposit nullifier prevents double credit. Confirm the executed funding receipt and account balance before spending.

## Open the recipient account and send

Select the recipient wallet to open its account for the chosen Asset, then select the funded payer wallet to transfer. Identity sequence and source-account sequence are obtained separately. The signing flow discloses the debit authorization and outer activity, including recipient, amount, Asset, fee ceiling, expiry, network, and idempotency key.

```
# Run with the recipient wallet selected.
layerx --rpc "$RPC_URL" --gateway-credential beta wallet open-account \
  --asset "$ASSET_ID" --receipt-policy "$RECEIPT_POLICY" \
  --fee-limit "$FEE_LIMIT"

# Select the funded payer before sending.
layerx key default alice
layerx --rpc "$RPC_URL" --gateway-credential beta wallet send \
  --to "$RECIPIENT_DID" --asset "$ASSET_ID" --amount 10 \
  --wait executed --receipt-policy "$RECEIPT_POLICY" \
  --fee-limit "$FEE_LIMIT"
```

Choose `executed` for a verified execution receipt, `batched` for authenticated batch inclusion, or `finalised` for matching finalised checkpoint evidence. The exact wire spelling is `finalised`.

## Recover a pending native payment

Each new CLI write creates a new idempotency key. If the first attempt times out, save its activity identifier and recover the original receipt instead of repeating `wallet send`.

```
layerx --rpc "$RPC_URL" --gateway-credential beta wallet receipt \
  "$ACTIVITY_ID" --receipt-policy "$RECEIPT_POLICY" --wait finalised
```

The receipt wait accepts `--timeout-seconds` from 1 to 300, defaulting to 60. Stream notifications are wake-ups: reconcile them with verified reads or a receipt wait.

## Equivalent public JSON-RPC submission

Submit already prepared and signed canonical bytes to the public router. State-changing requests require a gateway key with `activity:write`. The example uses placeholders for your own bytes and credentials.

```
POST /rpc
Authorization: LayerX-Key <key-id>:<key-secret>
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "lx_sendActivity",
  "params": ["<canonical signed activity hex>", "executed"]
}
```

Read `lx_getActivityStatus([activity_id])` or `lx_getReceipt([activity_id])` to recover evidence. For inclusion, request `lx_getProof(["receipt", activity_id])`. A bounded commitment wait that cannot establish the requested evidence returns JSON-RPC `-32001` with `state: "pending"`; it is not a successful payment.

## Handle common failures

| Code or condition | Response |
| --- | --- |
| `idempotency-required` | Supply the persistent purchase key before committing. |
| `idempotency-conflict` | Resolve the original request; do not reuse its key for a different body. |
| `rate-limit` | Respect the carried retry timing. |
| `unknown-outcome` | Recover the original payment by key and evidence. |
| `budget-refusal` | Inspect the funded budget and approved spending limits. |
| Invalid signature, stale sequence, missing scope, or evidence mismatch | Resolve the specific refusal before preparing any new payment. |

## Next steps

- [Payment lifecycle and merchant workflows](https://docs.paxeer.app/payments)

- [Create an Asset and manage accounts](https://docs.paxeer.app/assets)

- [Custody-backed funding](https://docs.paxeer.app/custody)

- [Charge for HTTP resources](https://docs.paxeer.app/paid-apis)

- [Estimate fees and set limits](https://docs.paxeer.app/fees)

- [Public payment API reference](https://docs.paxeer.app/platform-api)
