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

# Endpoints

> Complete reference of Payment SDK API endpoints

## Base URL

| Environment | Base URL                            |
| ----------- | ----------------------------------- |
| Production  | `https://api.pay.grain.inc`         |
| Sandbox     | `https://api.sandbox.pay.grain.inc` |

***

## Payment Sessions

### Create Payment Session

```
POST /payment-sessions
```

Create a new payment session. Returns a session ID and token for the client-side SDK.

**Headers:**

| Header          | Value                      |
| --------------- | -------------------------- |
| `Authorization` | `Bearer {CUBEPAY_API_KEY}` |
| `Content-Type`  | `application/json`         |

**Request Body:**

| Parameter   | Type     | Required | Description                                                   |
| ----------- | -------- | -------- | ------------------------------------------------------------- |
| `amount`    | `string` | Yes      | Payment amount as a decimal string (e.g., `"50.00"`)          |
| `currency`  | `string` | Yes      | Currency code (e.g., `"USD"`)                                 |
| `requestId` | `string` | No       | Idempotency key — your own UUID to prevent duplicate sessions |

**Example:**

```bash theme={null}
curl -X POST https://api.pay.grain.inc/payment-sessions \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"amount": "50.00", "currency": "USD", "requestId": "ord_12345"}'
```

**Response** `200 OK`:

```json theme={null}
{
  "paymentSessionId": "ps_abc123def456",
  "paymentSessionToken": "eyJhbGciOiJIUzI1NiIs...",
  "amount": "50.00",
  "currency": "USD",
  "network": "ETHEREUM",
  "tokenSymbol": "USDC",
  "oneTimeWalletAddress": "0x1234...abcd",
  "userAddress": null,
  "fundingTransactionHash": null,
  "status": "PENDING",
  "createdAt": "2026-03-20T12:00:00Z"
}
```

***

### Get Payment Session

```
GET /payment-sessions/{paymentSessionId}
```

Retrieve the current state of a payment session.

**Headers:**

| Header          | Value                          |
| --------------- | ------------------------------ |
| `Authorization` | `Bearer {paymentSessionToken}` |

**Example:**

```bash theme={null}
curl https://api.pay.grain.inc/payment-sessions/ps_abc123def456 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
```

**Response** `200 OK`:

```json theme={null}
{
  "paymentSessionId": "ps_abc123def456",
  "status": "FUNDED",
  "amount": "50.00",
  "currency": "USD",
  "network": "ETHEREUM",
  "tokenSymbol": "USDC",
  "userAddress": "0xCustomerWallet...",
  "oneTimeWalletAddress": "0xOTW...",
  "fundingTransactionHash": "0xabc123...",
  "userSubmittedTransactionHash": "0xdef456...",
  "createdAt": "2026-03-20T12:00:00Z"
}
```

***

## Captures

### Create Capture

```
POST /api/v1/payment-sessions/{paymentSessionId}/captures
```

Transfer funds from the one-time wallet (OTW) to your treasury wallet. Supports partial and final captures. Only available when the session status is `FUNDED`.

**Headers:**

| Header          | Value                      |
| --------------- | -------------------------- |
| `Authorization` | `Bearer {CUBEPAY_API_KEY}` |
| `Content-Type`  | `application/json`         |

**Request Body:**

| Parameter        | Type      | Required | Description                                                                                                  |
| ---------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------ |
| `requestId`      | `string`  | Yes      | Idempotency key to prevent duplicate captures                                                                |
| `captureAmount`  | `string`  | Yes      | Amount to capture (e.g., `"50.00"`)                                                                          |
| `isFinalCapture` | `boolean` | No       | Default `false`. When `true`, remaining balance is refunded to the customer and session moves to `SUCCEEDED` |

**Example:**

```bash theme={null}
curl -X POST https://api.pay.grain.inc/api/v1/payment-sessions/ps_abc123def456/captures \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"requestId": "cap_ord_12345", "captureAmount": "50.00", "isFinalCapture": true}'
```

**Response** `202 Accepted`:

```json theme={null}
{
  "captureId": "cap_xyz789",
  "captureAmount": "50.00",
  "refundAmount": "0.00",
  "status": "CAPTURING"
}
```

***

### Get Capture

```
GET /api/v1/payment-sessions/{paymentSessionId}/captures/{captureId}
```

Check the status of a capture operation.

**Headers:**

| Header          | Value                      |
| --------------- | -------------------------- |
| `Authorization` | `Bearer {CUBEPAY_API_KEY}` |

**Example:**

```bash theme={null}
curl https://api.pay.grain.inc/api/v1/payment-sessions/ps_abc123def456/captures/cap_xyz789 \
  -H "Authorization: Bearer your-api-key"
```

**Response** `200 OK`:

```json theme={null}
{
  "captureId": "cap_xyz789",
  "status": "CAPTURED",
  "captureAmount": "50.00",
  "refundAmount": "0.00",
  "captureTransferTransactionHash": "0xcapture123...",
  "refundTransferTransactionHash": null
}
```

### Capture Object

| Field                            | Type             | Description                                          |
| -------------------------------- | ---------------- | ---------------------------------------------------- |
| `captureId`                      | `string`         | Unique capture identifier                            |
| `status`                         | `string`         | `CAPTURING` (in progress) or `CAPTURED` (complete)   |
| `captureAmount`                  | `string`         | Amount captured                                      |
| `refundAmount`                   | `string`         | Amount refunded to customer (on final capture)       |
| `captureTransferTransactionHash` | `string \| null` | On-chain hash of the capture transfer                |
| `refundTransferTransactionHash`  | `string \| null` | On-chain hash of the refund transfer (if applicable) |

***

## Webhooks

### Payment Status Update

```
POST {your-webhook-url}
```

Grain sends payment status updates to your registered webhook URL as JSON-RPC 2.0 requests.

**Payload:**

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "1770947403693",
  "method": "cubepay_paymentStatusUpdate",
  "params": [
    {
      "merchantId": "your-merchant-id",
      "paymentSessionId": "ps_abc123def456",
      "status": "FUNDED",
      "updatedAt": "2026-03-20T12:05:00Z"
    }
  ]
}
```

**Status Values:**

| Status      | Description                                                   |
| ----------- | ------------------------------------------------------------- |
| `CREATED`   | Session created, customer has not connected a wallet yet      |
| `PENDING`   | Wallet connected, awaiting funding transaction                |
| `FUNDED`    | Funds received at the one-time wallet — ready to capture      |
| `CAPTURING` | Capture in progress (funds being transferred)                 |
| `SUCCEEDED` | Final capture complete — funds settled to your treasury       |
| `CANCELED`  | Session expired or was cancelled (not funded within 24 hours) |
| `ERROR`     | An error occurred during processing                           |

**Expected Response:**

Return `200` with a JSON-RPC acknowledgment:

```json theme={null}
{
  "jsonrpc": "2.0",
  "result": "ok"
}
```

***

## Response Fields Reference

### Payment Session Object

| Field                          | Type             | Description                                                            |
| ------------------------------ | ---------------- | ---------------------------------------------------------------------- |
| `paymentSessionId`             | `string`         | Unique session identifier                                              |
| `paymentSessionToken`          | `string`         | Short-lived token for client-side operations                           |
| `amount`                       | `string`         | Payment amount                                                         |
| `currency`                     | `string`         | Currency code                                                          |
| `network`                      | `string`         | Blockchain network (e.g., `ETHEREUM`, `SEPOLIA`)                       |
| `tokenSymbol`                  | `string`         | Token used for payment (e.g., `USDC`)                                  |
| `oneTimeWalletAddress`         | `string`         | Unique receiving address for this session                              |
| `userAddress`                  | `string \| null` | Customer's wallet address (populated after connection)                 |
| `fundingTransactionHash`       | `string \| null` | Transaction hash of the funding transfer                               |
| `userSubmittedTransactionHash` | `string \| null` | Transaction hash as submitted by the user's wallet                     |
| `capturableAmount`             | `string`         | Remaining balance available for capture                                |
| `capturedAmount`               | `string`         | Total amount captured so far                                           |
| `captures`                     | `array`          | Array of capture operations with their statuses and transaction hashes |
| `status`                       | `string`         | Current session status                                                 |
| `createdAt`                    | `string`         | ISO 8601 creation timestamp                                            |

<Note>
  All endpoints require [authentication](/payment-sdk/api-reference/authentication). See [Error Codes](/payment-sdk/api-reference/error-codes) for error response formats.
</Note>
