# Direct Link pay-in: APM

Trigger an APM pay-in with no Omno UI. Your backend creates and starts the transaction, then redirects the customer to the provider.

## Steps

### 1. Create the pay-in

`POST /v3/public/payin` with a `directRouteId` and the required `CreatePayInRequest` fields.

```bash
curl -X POST "https://api.omno.com/v3/public/payin" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "orderId": "order-2026-000202",
    "amount": 100.00,
    "currency": "EUR",
    "kycVerified": true,
    "previousTransactionCount": 5,
    "customer": {
      "externalUserId": "3183818381183",
      "firstName": "John",
      "lastName": "Doe",
      "email": "john.doe@example.com",
      "phoneNumber": "1 1234567890",
      "dateOfBirth": "1990-12-01",
      "billing": {
        "address": "123 Main St",
        "city": "Atlanta",
        "state": "GA",
        "countryCode": "US",
        "postalCode": "30308"
      }
    },
    "directRouteId": "944732c4608c441aa91379478b91f76e",
    "returnUrls": {
      "success": "https://merchant.example.com/success",
      "failure": "https://merchant.example.com/failure"
    }
  }'
```

Response:

```json
{
  "paymentId": "944732c4608c441aa91379478b91f76e",
  "status": "CREATED"
}
```

Direct Link uses the `redirectUrl` from step 2 to send the customer to the provider.

`CreatePayInRequest` fields:

| Field | Type | Required | Description | Example |
|  --- | --- | --- | --- | --- |
| `orderId` | string | Yes | Your unique identifier for the pay-in. | `order-2026-000202` |
| `amount` | number | Yes | Pay-in amount. | `100.00` |
| `currency` | string | Yes | ISO 4217 currency. | `EUR` |
| `kycVerified` | boolean | Yes | Whether the customer is KYC-verified in your system. | `true` |
| `previousTransactionCount` | integer | Yes | Previous transactions in your system. | `5` |
| `customer` | object | Yes | [`CustomerRequest`](/apis). |  |
| `returnUrls` | object | Yes | `success` and `failure` URLs. |  |
| `directRouteId` | string | Yes (Direct Link) | Direct Link Route ID. | `944732c4608c441aa91379478b91f76e` |
| `merchantAdditionalData` | object | No | Additional data for the transaction. |  |


### 2. Start processing

`POST /v3/public/payin/{payinId}/process/direct-link` with `browser` and `additionalData`.

```bash
curl -X POST \
  "https://api.omno.com/v3/public/payin/944732c4608c441aa91379478b91f76e/process/direct-link" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "browser": {
      "acceptHeader": "text/html,application/xhtml+xml",
      "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
      "language": "en-US",
      "timeZoneOffset": -60,
      "timeZone": "Europe/Berlin",
      "colorDepth": 24,
      "screenHeight": 1080,
      "screenWidth": 1920,
      "windowHeight": 969,
      "windowWidth": 1920,
      "javaEnabled": false,
      "javascriptEnabled": true,
      "customerIp": "203.0.113.10"
    },
    "additionalData": {}
  }'
```

Response:

```json
{
  "paymentId": "944732c4608c441aa91379478b91f76e",
  "status": "PENDING",
  "redirectUrl": "https://psp.example.com/redirect/944732c4608c441aa91379478b91f76e"
}
```

`additionalData` carries method-specific fields for the chosen APM. Your Omno integration team provides the exact keys for your providers.

### 3. Redirect the customer

Send the customer to `redirectUrl` from the response to complete the payment.

### 4. Final status

Determine the outcome from a [webhook](/guides/concepts/webhooks) or a GET on the transaction.

## The `Browser` object

Collect these values client-side (they support 3DS and fraud checks).

| Field | Type | How to collect |
|  --- | --- | --- |
| `acceptHeader` | string | Server-side `Accept` request header. |
| `userAgent` | string | `navigator.userAgent`. |
| `language` | string | `navigator.language`. |
| `timeZoneOffset` | integer | `new Date().getTimezoneOffset()` (minutes). |
| `timeZone` | string | `Intl.DateTimeFormat().resolvedOptions().timeZone`. |
| `colorDepth` | integer | `screen.colorDepth`. |
| `screenHeight` | integer | `screen.height`. |
| `screenWidth` | integer | `screen.width`. |
| `windowHeight` | integer | `window.innerHeight`. |
| `windowWidth` | integer | `window.innerWidth`. |
| `javaEnabled` | boolean | `navigator.javaEnabled()`. |
| `javascriptEnabled` | boolean | `true` when collected in-browser. |
| `customerIp` | string | Customer IP (from your server). |


## Failure states

- **Decline** — `DECLINED` (via webhook/GET).
- **PSP failure** — `FAILED`.
- **Timeout** — `TIMEOUT`; may resolve later.
- **Customer abandons** — no completion at the provider; reconcile via GET.
- **Pending resolving asynchronously** — `PENDING`; final status via webhook.


## Build it →

- [Pay-in: crypto](/direct-link/payin-crypto) · [Payout](/direct-link/payout) · [Other APIs → Pay-ins](/apis)