> ## 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.

# Create and Process Your First Payment with Nova.Pay

> Step-by-step guide to processing checkout payments with Nova.Pay via credit card, Pix, or bank slip — from payment plans to handling the response.

Nova.Pay's checkout flow is built around three core steps: fetch the available payment plans for your product, tokenize sensitive card data client-side, and submit the payment. This guide walks you through each step end-to-end and explains how to interpret the response so you can deliver a smooth experience to your customers.

<Steps>
  <Step title="Get Available Payment Plans">
    Before presenting a checkout form, retrieve the payment plans associated with your product. Each plan describes an available payment method (credit card, Pix, boleto) along with instalment options and pricing.

    **Endpoint:** `GET /payment_plans`

    | Query parameter    | Description                                                       |
    | ------------------ | ----------------------------------------------------------------- |
    | `checkout_page_id` | UUID of the checkout page                                         |
    | `charge_id`        | ID of a specific charge (alternative to `checkout_page_id`)       |
    | `cart_id`          | ID of a cart object (alternative to `checkout_page_id`)           |
    | `amount`           | Override amount in cents (alternative to `checkout_page_id`)      |
    | `coupon`           | Optional coupon code — returned amounts will reflect the discount |

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

    The response contains an array of plan objects. The `id` field (e.g. `"42-3"`) is the `payment_plan_id` you will pass to `POST /payments`.

    ```json theme={null}
    [
      {
        "id": "42-1",
        "payment_method": "credit_card",
        "instalments": 1,
        "amount": 9700,
        "instalment_amount": 9700,
        "currency": "BRL",
        "description": "Credit card – 1× of R$ 97.00"
      },
      {
        "id": "42-3",
        "payment_method": "credit_card",
        "instalments": 3,
        "amount": 9700,
        "instalment_amount": 3400,
        "currency": "BRL",
        "description": "Credit card – 3× of R$ 34.00"
      },
      {
        "id": "43-1",
        "payment_method": "pix",
        "instalments": 1,
        "amount": 8900,
        "instalment_amount": 8900,
        "currency": "BRL",
        "description": "Pix – 1× of R$ 89.00"
      }
    ]
    ```
  </Step>

  <Step title="Tokenize the Card (Credit Card Only)">
    Nova.Pay never receives raw card numbers. Card data must be tokenized **client-side** using the gateway's own SDK before you submit the payment. Nova.Pay supports both Pagar.me and Stripe as card gateways.

    <Note>
      Never send raw card numbers to the Nova.Pay API. Always tokenize card data using the gateway SDK running in the customer's browser.
    </Note>

    <Tabs>
      <Tab title="Pagar.me">
        Use the Pagar.me.js SDK to create a card token. The returned `token` string (e.g. `tok_abc123`) is what you pass to `POST /payments` as `credit_card_0_token`.

        ```js theme={null}
        const pagarme = await PagarMe.init({ publicKey: "pk_live_..." });

        const cardToken = await pagarme.fields.getCreditCardToken({
          holderName: "Maria Silva",
          number: "4111111111111111",
          expirationMonth: "12",
          expirationYear: "2027",
          cvv: "123",
        });

        console.log(cardToken.token); // "tok_abc123"
        ```
      </Tab>

      <Tab title="Stripe">
        Use Stripe.js to create a `ConfirmationToken`. Pass the returned `confirmation_token_id` as `credit_card_0_token` in the Nova.Pay request body.

        ```js theme={null}
        const stripe = Stripe("pk_live_...");

        const { confirmationToken, error } = await stripe.createConfirmationToken({
          elements, // your Stripe Elements instance
        });

        console.log(confirmationToken.id); // "ctoken_abc123"
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Submit the Payment">
    Call `POST /payments` with the `payment_plan_id` from Step 1, the gateway token from Step 2 (credit card only), and the customer's contact details.

    **Endpoint:** `POST /payments`\
    **Base URL:** `https://pay.nova.money/api/v1`

    <Tabs>
      <Tab title="Credit Card">
        ```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",
            "credit_card_0_token": "tok_abc123",
            "credit_card_0_payment_plan": "42-1"
          }'
        ```
      </Tab>

      <Tab title="Pix">
        No card token is required for Pix. Nova.Pay generates a QR code and returns it in the response.

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

      <Tab title="Boleto">
        Nova.Pay generates a bank slip (boleto) URL and returns it in the response.

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

  <Step title="Handle the Response">
    A successful request returns HTTP `200` with a `PaymentResult` object. Inspect `order_status` first, then branch based on the payment method used.

    <ResponseField name="order_status" type="string" required>
      Overall status of the order (e.g. `"paid"`, `"pending"`, `"refused"`).
    </ResponseField>

    <ResponseField name="payments" type="array">
      Array of gateway-level payment IDs created for this order.
    </ResponseField>

    <ResponseField name="bank_slip_url" type="string">
      URL to the generated boleto PDF. Present only when the payment method is `boleto`.
    </ResponseField>

    <ResponseField name="pix_qr_code" type="string">
      Base64-encoded Pix QR code image. Present only for Pix payments.
    </ResponseField>

    <ResponseField name="pix_qr_code_url" type="string">
      Hosted URL for the Pix QR code image. Present only for Pix payments.
    </ResponseField>

    <ResponseField name="pix_expires_at" type="string">
      ISO 8601 timestamp indicating when the Pix QR code expires. Present only for Pix payments.
    </ResponseField>

    <ResponseField name="redirect_url" type="string">
      Success redirect URL if one is configured on the checkout page. Redirect the customer here after displaying confirmation.
    </ResponseField>

    <ResponseField name="offer" type="string">
      Signed GlobalID (SGID) of an upsell offer, if the checkout page has one configured and the payment succeeded.
    </ResponseField>

    <ResponseField name="is_subscription" type="boolean">
      `true` when the purchased product is a subscription. Use this to show appropriate messaging to the customer.
    </ResponseField>

    <Tip>
      If the response contains an `offer` field, you can present the customer with a one-click upsell — no card re-entry needed. See the [Upsell guide](/guides/upsell) for details.
    </Tip>
  </Step>
</Steps>

***

## Two-Card Split Payment

Nova.Pay supports splitting a payment across two credit cards. Include both tokens and their respective payment plan assignments in the request body.

```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",
    "credit_card_0_token": "tok_abc123",
    "credit_card_0_payment_plan": "42-1",
    "credit_card_1_token": "tok_xyz789",
    "credit_card_1_payment_plan": "42-1"
  }'
```

Each card is charged independently by the gateway. The `payments` array in the response will contain two entries — one per card.


## Related topics

- [Nova.Pay API: Payments, Checkout & Order Management](/introduction.md)
- [Webhooks API — Handle Payment Gateway Event Callbacks](/api-reference/webhooks.md)
- [How to Validate and Apply Discount Coupons in Nova.Pay](/guides/coupons.md)
- [Receive and Handle Payment Webhook Events in Nova.Pay](/guides/webhooks.md)
- [Build a Custom Nova.Pay Checkout with AI](/guides/ai-checkout-skill.md)
