---
title: "Take NMI payments with the Jovvie PHP SDK"
description: "Create NMI payments, send them to a terminal, and manage the merchant's terminals with the Jovvie NMI SDK."
url: https://docs.jovvie.com/developers/nmi-payments/
section: "Developers"
last_updated: 2026-10-26
---

# Take NMI payments with the Jovvie PHP SDK

Section: Developers

> Create NMI payments, send them to a terminal, and manage the merchant's terminals with the Jovvie NMI SDK.

This page shows you how to take in-person payments for a merchant who uses NMI. You use the NMI SDK to manage the merchant’s terminals (called devices in the SDK), create a payment, and either send it straight to a terminal or send your staff to the Jovvie payment page.

The NMI SDK works a little differently from the Stripe SDK:

- The client takes only the public key and the secret key.
- There are no authorization links. You choose per payment whether the payment page asks for the Access PIN.
- You can send a payment straight to a terminal when you create it.
- There are no recurring payments.

For the Stripe SDK, see [Create a payment (Stripe)](https://docs.jovvie.com/developers/create-a-payment/). For a side-by-side view, see [Stripe and NMI: what’s different](https://docs.jovvie.com/payments/stripe-vs-nmi/).

## Before you start

- You installed the NMI SDK. See [Install the SDK](https://docs.jovvie.com/developers/install-the-sdk/).
- The merchant’s NMI account is connected, and you have the server application keys. See [Get started](https://docs.jovvie.com/developers/get-started/).

```php
<?php
use JovviePaymentsGateway\JovviePaymentsGatewayClient;

$client = new JovviePaymentsGatewayClient('YOUR_PUBLIC_KEY', 'YOUR_SECRET_KEY');
```

## Manage terminals

Each terminal you register gets a Jovvie device ID (`publicId`). You use this ID to send a payment to that terminal.

| Method                                        | What it does                                                                |
| --------------------------------------------- | --------------------------------------------------------------------------- |
| `devices()->list()`                           | Returns all of the merchant’s registered devices.                           |
| `devices()->get($deviceId)`                   | Returns one device.                                                         |
| `devices()->create($registrationCode, $name)` | Registers a terminal with its registration code and returns the new device. |
| `devices()->delete($deviceId)`                | Removes the device from the merchant’s account.                             |

Each device has these fields:

| Field          | What it is                                         |
| -------------- | -------------------------------------------------- |
| `publicId`     | The Jovvie device ID.                              |
| `name`         | The device name. Staff see it on the payment page. |
| `serialNumber` | The terminal’s serial number, if known.            |
| `createdAt`    | When the device was registered.                    |

### Register a terminal

1. Get the terminal’s registration code.
2. Choose a name for it, from 1 to 20 characters. Use only letters, numbers, spaces, dashes (-), and underscores (\_).
3. Call `devices()->create()` with the code and the name.
4. Save the returned `publicId` if you want to send payments to this terminal.

```php
<?php
$device = $client->devices()->create('YOUR_REGISTRATION_CODE', 'Front Counter');

echo $device->publicId;
```

> **Note**
>
> Always pass a terminal name.

If the registration code is not accepted, the SDK throws a `ResponseError`. See [Handle errors](https://docs.jovvie.com/developers/errors/).

## Create a payment

Call `payments()->create($amount, $currency, $description, $options)`.

| Argument       | What it is                                                                                                   |
| -------------- | ------------------------------------------------------------------------------------------------------------ |
| `$amount`      | The amount to charge, as an integer in the smallest currency unit. For example, `2500` for 25.00 USD.        |
| `$currency`    | A three-letter ISO currency code, such as `usd`. Use a currency with two decimal places.                     |
| `$description` | A description of the payment. It cannot be empty. The payment page shows it as the only line of the payment. |
| `$options`     | Optional. See the table of options in this section.                                                          |

| Option              | What it does                                                                                                                                                                            |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `returnUrl`         | Where the browser goes after the payment page is done. Must be a full URL.                                                                                                              |
| `cancelUrl`         | Where the browser goes when staff click **← Back** and the payment is `cancelled`. A `pending` payment is first marked `cancelled`. Other statuses use `returnUrl`. Must be a full URL. |
| `deviceId`          | A Jovvie device ID. Jovvie sends the payment to that terminal right away.                                                                                                               |
| `paymentMethodType` | `request-terminal` (the default) makes the payment page ask for the Access PIN. `terminal` shows the terminals without the PIN.                                                         |

If you leave out `returnUrl` or `cancelUrl`, Jovvie uses its own payment status page in place of the missing URL. A URL you do pass still works as usual. Pass both so staff return to your app for either outcome.

```php
<?php
$payment = $client->payments()->create(
    2500,
    'usd',
    'Order YOUR_ORDER_ID',
    [
        'returnUrl' => 'YOUR_RETURN_URL',
        'cancelUrl' => 'YOUR_CANCEL_URL',
        'deviceId' => 'YOUR_DEVICE_ID',
    ]
);

// Save these with your order.
$paymentId = $payment->id;
$checkoutLink = $payment->generatedData->checkoutLink;
```

The method returns a `OneTimePayment` object with these fields:

| Field                         | What it is                                            |
| ----------------------------- | ----------------------------------------------------- |
| `id`                          | The Jovvie payment ID. Save it with your order.       |
| `status`                      | The payment status. A new payment is `pending`.       |
| `amount`, `currency`          | The amount (smallest currency unit) and currency.     |
| `generatedData->checkoutLink` | The link to the Jovvie payment page for this payment. |

To get the NMI transaction ID, use `getTransactionId()` on a verified NMI webhook event, such as `jovvie-gateway.payment.completed`. See [Handle webhooks](https://docs.jovvie.com/developers/webhooks/#nmi-sdk-events).

If the device ID does not belong to the merchant, the SDK throws a `BadRequestError`.

## Take the payment

How staff take the payment depends on whether you passed a `deviceId`.

**With a device ID:** Jovvie sends the payment to that terminal as soon as you create it. The customer can pay on the terminal right away. If you also open the checkout link, the payment page asks for the Access PIN (unless `paymentMethodType` is `terminal`), then shows **Pay with Device** while it waits for the customer to finish on the terminal.

**Without a device ID:**

1. Send a staff member’s browser to the checkout link.
2. If the page shows **Enter PIN**, the staff member enters the Access PIN and clicks **Continue**.
3. Under **Choose a reader**, the staff member selects a terminal.
4. The staff member clicks **Process Payment**.
5. The customer pays on the terminal.

For how staff take an NMI payment in Point of Sale, see [Take a card payment with an NMI terminal](https://docs.jovvie.com/point-of-sale/sell/card-payment-nmi/).

> **Caution**
>
> Treat the checkout link like a key to this payment. Show it only to the merchant’s staff. If you set `paymentMethodType` to `terminal`, anyone who has the checkout link can send the payment to the merchant’s terminals without the Access PIN. Use `terminal` only when the link goes to signed-in staff.

## Confirm the payment

A visit to your return URL does not prove that the customer paid.

1. Look up the Jovvie payment ID you saved for this order.
2. Fetch the payment with `$client->payments()->get($paymentId)`.
3. Mark the order paid only if `status` is `completed`.

Also handle NMI webhooks, which tell you when a payment completes, fails, is cancelled, or is refunded. See [Handle webhooks](https://docs.jovvie.com/developers/webhooks/) and [Check a payment’s status](https://docs.jovvie.com/developers/check-payment-status/).

If a payment’s outcome is unclear, do not create a second payment for the same order until you have confirmed that the first one did not go through and is not still processing.

## Refunds

The NMI SDK cannot refund a payment yet. SDK support for refunds is planned. Refunds are made in the NMI portal. See [Refunds](https://docs.jovvie.com/developers/refunds/).

## Related pages

- [Handle webhooks](https://docs.jovvie.com/developers/webhooks/)
- [Check a payment’s status](https://docs.jovvie.com/developers/check-payment-status/)
- [Handle errors](https://docs.jovvie.com/developers/errors/)
