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

# How to Validate and Apply Discount Coupons in Nova.Pay

> Learn how to validate coupon codes, retrieve discount values, and apply coupons to payments and payment plan calculations in Nova.Pay.

Nova.Pay supports coupon codes that reduce the order total for your customers. The recommended flow is to validate the coupon code first so you can display the discounted price before checkout, then pass the code when fetching payment plans and again when submitting the payment. This ensures the discount is applied consistently at every stage of the purchase.

***

## Step 1: Validate a Coupon

Before showing the discounted price to a customer, verify that the coupon code exists, is active, and applies to the product being purchased.

**Endpoint:** `GET /coupons/{code}/validate`

| Query parameter | Description                                  |
| --------------- | -------------------------------------------- |
| `product_id`    | ID of the product the customer is purchasing |

```bash theme={null}
curl -G "https://pay.nova.money/api/v1/coupons/SUMMER20/validate" \
  --data-urlencode "product_id=101"
```

**Response:**

```json theme={null}
{
  "code": "SUMMER20",
  "value": 20.0,
  "type": "percentage"
}
```

<ResponseField name="code" type="string" required>
  The coupon code as stored in Nova.Pay (normalized, uppercased).
</ResponseField>

<ResponseField name="value" type="number" required>
  The discount magnitude. Interpretation depends on `type`:

  * When `type` is `"percentage"`, this is the percentage to deduct (e.g. `20.0` = 20% off).
  * When `type` is `"price"`, this is the fixed amount to deduct in the currency's major unit (e.g. `15.0` = R\$ 15.00 off).
</ResponseField>

<ResponseField name="type" type="string" required>
  Discount strategy. One of:

  | Value        | Meaning                                    |
  | ------------ | ------------------------------------------ |
  | `percentage` | Deduct a percentage of the order total     |
  | `price`      | Deduct a fixed amount from the order total |
</ResponseField>

<Note>
  If the coupon code is invalid, expired, or does not apply to the specified product, the API returns `422 Unprocessable Entity` with a descriptive error message. Always handle this case in your UI so customers can correct the code.
</Note>

***

## Step 2: Fetch Payment Plans with the Coupon

Once you have a valid coupon, pass it as the `coupon` query parameter when fetching payment plans. Nova.Pay recalculates plan amounts server-side and returns prices that already reflect the discount — you can display these directly to the customer without any client-side arithmetic.

**Endpoint:** `GET /payment_plans`

```bash theme={null}
curl -G "https://pay.nova.money/api/v1/payment_plans" \
  --data-urlencode "checkout_page_id=550e8400-e29b-41d4-a716-446655440000" \
  --data-urlencode "coupon=SUMMER20"
```

The response structure is identical to a normal `/payment_plans` call, but `amount` and `instalment_amount` values are already discounted.

```json theme={null}
[
  {
    "id": "42-1",
    "payment_method": "credit_card",
    "instalments": 1,
    "amount": 7760,
    "instalment_amount": 7760,
    "currency": "BRL",
    "description": "Credit card – 1× of R$ 77.60"
  },
  {
    "id": "43-1",
    "payment_method": "pix",
    "instalments": 1,
    "amount": 7120,
    "instalment_amount": 7120,
    "currency": "BRL",
    "description": "Pix – 1× of R$ 71.20"
  }
]
```

***

## Step 3: Apply the Coupon at Payment Time

Include the `coupon` field in your `POST /payments` request body. Nova.Pay validates the coupon again server-side and applies the discount to the charge.

**Endpoint:** `POST /payments`

```bash theme={null}
curl -X POST "https://pay.nova.money/api/v1/payments" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_plan_id": "42-1",
    "checkout_page_id": "550e8400-e29b-41d4-a716-446655440000",
    "customer_email": "customer@example.com",
    "customer_phone": "11999998888",
    "coupon": "SUMMER20",
    "credit_card_0_token": "tok_abc123",
    "credit_card_0_payment_plan": "42-1"
  }'
```

***

## Full End-to-End Example

Here is a complete `POST /payments` request body that combines a coupon with a credit card payment:

```json theme={null}
{
  "payment_plan_id": "42-1",
  "checkout_page_id": "550e8400-e29b-41d4-a716-446655440000",
  "customer_email": "customer@example.com",
  "customer_phone": "11999998888",
  "coupon": "SUMMER20",
  "credit_card_0_token": "tok_abc123",
  "credit_card_0_payment_plan": "42-1"
}
```

And the same flow with Pix — no card fields needed:

```json theme={null}
{
  "payment_plan_id": "43-1",
  "checkout_page_id": "550e8400-e29b-41d4-a716-446655440000",
  "customer_email": "customer@example.com",
  "customer_phone": "11999998888",
  "coupon": "SUMMER20"
}
```

<Note>
  If the coupon code passed in `POST /payments` is invalid or does not apply to the selected products, Nova.Pay returns `422 Unprocessable Entity` with an error message identifying the problem. Make sure your checkout UI surfaces this error clearly so customers can enter a different code or proceed without a coupon.
</Note>


## Related topics

- [Coupons API — Validate Discount Codes Before Checkout](/api-reference/coupons.md)
- [Payment Plans API — List and Retrieve Installment Options](/api-reference/payment-plans.md)
- [Nova.Pay Checkout Flow: Pages, Carts, and Charge Links](/concepts/checkout-flow.md)
- [Create and Process Your First Payment with Nova.Pay](/guides/create-payment.md)
- [Nova.Pay API Authentication: Keys, Hosts & Webhooks](/authentication.md)
