<!-- ZenPays documentation · https://docs.zenpayz.com/docs/rest-api/endpoints/ramp/get-ramp-intent -->

# Get Ramp Intent

Retrieve the full details of a ramp intent, including the generated widget URL for embedding. This endpoint also manages automatic status transitions — the intent moves from `created` to `active` on the first GET request, and auto-expires if past its `expiresAt` timestamp.

<EndpointHeader verb="GET" path="/payment/api/v1/ramp-intents/:intentId" />

## Request

### Headers

<ParamTable
  label="Header"
  rows={[
    { name: "x-request-id", desc: "Custom request ID for tracing" },
  ]}
/>

:::note Public Endpoint
This endpoint does not require authentication headers. It is designed to be called from your frontend or checkout page.
:::

### Path Parameters

<ParamTable
  rows={[
    { name: "intentId", type: "string", required: true, desc: "The ramp intent ID (e.g. `ri_1710345678000_a1b2c3d4e5f6g7h8`)" },
  ]}
/>

## Response

### Success (200 OK)

```json
{
  "success": true,
  "data": {
    "intent": {
      "intentId": "ri_1710345678000_a1b2c3d4e5f6g7h8",
      "type": "buy",
      "fiatCurrency": "USD",
      "cryptoCurrency": "eth_ethereum",
      "amount": 100,
      "status": "active",
      "kycStatus": "approved",
      "cancelReason": null,
      "wallets": [
        { "network": "ethereum", "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28" }
      ],
      "userId": "usr_abc123",
      "kycVerified": true,
      "successUrl": "https://yourapp.com/success",
      "cancelUrl": "https://yourapp.com/cancel",
      "expiresAt": "2026-03-15T10:00:00.000Z",
      "metadata": {}
    },
    "widgetUrl": "https://widget.onramper.com/...signed_url..."
  },
  "message": "Ramp intent retrieved"
}
```

### Response Fields

#### Intent Object

<ParamTable
  rows={[
    { name: "intentId", type: "string", desc: "Unique intent identifier" },
    { name: "type", type: "string", desc: "`buy` or `sell`" },
    { name: "fiatCurrency", type: "string", desc: "Fiat currency code" },
    { name: "cryptoCurrency", type: "string | null", desc: "Crypto identifier" },
    { name: "amount", type: "number | null", desc: "Default amount" },
    { name: "status", type: "string", desc: "Lifecycle state: `created`, `active`, `completed`, `expired`, or `cancelled`" },
    { name: "kycStatus", type: "string", desc: "KYC sub-state: `pending`, `in_review`, `approved`, `declined`, or `expired`. When KYC is declined, `status` flips to `cancelled` and `cancelReason='kyc_rejected'`." },
    { name: "cancelReason", type: "string | null", desc: "Reason the intent was cancelled. `kyc_rejected` when KYC was declined; `kyc_expired` for KYC session expiry. `null` otherwise." },
    { name: "successUrl", type: "string | null", desc: "Merchant success redirect URL" },
    { name: "cancelUrl", type: "string | null", desc: "Merchant cancel redirect URL" },
    { name: "expiresAt", type: "string", desc: "Expiry timestamp" },
    { name: "metadata", type: "object", desc: "Custom metadata" },
    { name: "wallets", type: "array", desc: "Array of `{ network, address }` wallet objects" },
    { name: "userId", type: "string", desc: "Merchant's user identifier (KYC record key)" },
    { name: "kycVerified", type: "boolean", desc: "Whether KYC was pre-verified by merchant. Convenience flag — equivalent to `kycStatus === 'approved'`." },
    { name: "customerEmail", type: "string | null", desc: "Customer email if provided" },
  ]}
/>

#### Root Fields

<ParamTable
  rows={[
    { name: "widgetUrl", type: "string | null", desc: "Signed widget URL for iframe embedding. `null` if expired." },
    { name: "kycRequired", type: "boolean | undefined", desc: "Whether ZenPays KYC verification is required. Present when `kycVerified` is `false` and the user has not yet been verified." },
    { name: "kycVerificationUrl", type: "string | null", desc: "URL to redirect user for identity verification. `null` if no verification session has been initiated yet." },
  ]}
/>

### KYC Gating

The response shape depends on the user's KYC status:

**Scenario 1: KYC pre-verified by merchant** (`kycVerified: true` on the intent)

Widget URL is returned immediately. No KYC prompts.

**Scenario 2: KYC verified via ZenPays** (`kycVerified: false`, user already verified)

Widget URL is returned. `kycRequired` is absent or `false`.

**Scenario 3: KYC required** (`kycVerified: false`, user not verified)

`widgetUrl` is `null`, `kycRequired` is `true`. If a verification session exists, `kycVerificationUrl` contains the URL. If not, call [`initiateKyc`](/docs/api-reference/ramp-intents#initiatekyc) (or the equivalent REST endpoint) to create a session.

```json
{
  "success": true,
  "data": {
    "intent": {
      "intentId": "ri_1710345678000_a1b2c3d4e5f6g7h8",
      "type": "sell",
      "fiatCurrency": "INR",
      "status": "active",
      "wallets": [{ "network": "ethereum", "address": "0x742d..." }],
      "userId": "usr_abc123",
      "kycVerified": false,
      "expiresAt": "2026-03-15T10:00:00.000Z"
    },
    "widgetUrl": null,
    "kycRequired": true,
    "kycVerificationUrl": "https://verify.zenpayz.com/session/abc123"
  },
  "message": "Ramp intent retrieved"
}
```

### Automatic Behaviors

| Condition | Action |
|-----------|--------|
| Intent status is `created` | Auto-transitions to `active` on first GET |
| `expiresAt` has passed | Auto-transitions to `expired`, returns `widgetUrl: null` |
| Widget URL not yet cached | Generates and caches the widget URL |
| Intent in `awaiting_payout` phase | Skips widget URL generation (sell flow Phase 2) |

### Error Responses

<ErrorTable
  rows={[
    { code: "NOT_FOUND", status: "404", message: "Intent with the given ID does not exist" },
  ]}
/>

<CodeRail>

## Examples

<Tabs groupId="language">
  <TabItem value="curl" label="cURL" default>

```bash
curl https://api.zenpayz.com/payment/api/v1/ramp-intents/ri_1710345678000_a1b2c3d4e5f6g7h8
```

  </TabItem>
  <TabItem value="javascript" label="JavaScript">

```javascript
const intentId = 'ri_1710345678000_a1b2c3d4e5f6g7h8';

const response = await fetch(
  `https://api.zenpayz.com/payment/api/v1/ramp-intents/${intentId}`
);

const { data } = await response.json();
const { intent, widgetUrl } = data;

if (intent.status === 'expired') {
  console.log('Intent has expired — create a new one');
} else if (widgetUrl) {
  // Embed in an iframe
  const iframe = document.createElement('iframe');
  iframe.src = widgetUrl;
  iframe.style.width = '100%';
  iframe.style.height = '600px';
  iframe.style.border = 'none';
  document.getElementById('widget-container').appendChild(iframe);
}
```

  </TabItem>
  <TabItem value="python" label="Python">

```python
import requests

intent_id = "ri_1710345678000_a1b2c3d4e5f6g7h8"

response = requests.get(
    f"https://api.zenpayz.com/payment/api/v1/ramp-intents/{intent_id}"
)

data = response.json()["data"]
intent = data["intent"]
widget_url = data["widgetUrl"]

print(f"Status: {intent['status']}")
print(f"Type: {intent['type']}")

if intent["status"] == "expired":
    print("Intent has expired — create a new one")
elif widget_url:
    print(f"Widget URL: {widget_url}")
```

  </TabItem>
</Tabs>

</CodeRail>

## Next Steps

- [Create Ramp Intent](/docs/rest-api/endpoints/ramp/create-ramp-intent) — Create a new ramp intent
- [Update Ramp Intent Status](/docs/rest-api/endpoints/ramp/update-ramp-intent-status) — Manually transition status
- [Widget URL](/docs/rest-api/endpoints/ramp/widget-url) — Alternative widget URL generation
- [On-Ramp Flow](/docs/examples/on-ramp-flow) — Complete buy integration guide
