---
updatedAt: 2026-05-07T07:30:32.000Z
agentTools:
  projectIndex: https://docs.paymongo.com/llms.txt
---

# Quick start

The fastest path to accepting your first payment via the Payments API — step-by-step from creating a Payment Intent to handling the result.

## Overview

This guide walks you through the fastest path to a completed payment: a card payment via the Payment Intent workflow. By the end, you'll have working code that creates a Payment Intent, collects card details client-side, attaches them, handles 3D Secure authentication, and confirms success via webhook.

This is a single happy path — no branching, no multiple methods. Once you've completed this, see the [Cards](cards/index) and other payment method pages to expand your integration.

***

## Before you start

You need:

* A PayMongo account with an activated merchant profile
* Your **secret API key** and **public API key** from the PayMongo dashboard
* A backend server (any language) that can make HTTPS requests
* A frontend that can run JavaScript

All examples in this guide use **test API keys**. No real money moves. See [Testing](testing) for test card numbers.

***

## Step 1 — Create a Payment Intent (server-side)

From your **backend**, call the Create Payment Intent endpoint using your **secret API key**.

```javascript
const response = await fetch('https://api.paymongo.com/v1/payment_intents', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('sk_test_YOUR_SECRET_KEY:')
  },
  body: JSON.stringify({
    data: {
      attributes: {
        amount: 10000,
        currency: 'PHP',
        payment_method_allowed: ['card'],
        description: 'Order #1234'
      }
    }
  })
});
const intent = await response.json();
```

`amount` is in centavos. `10000` = PHP 100.00.

Save the `id` and send the `client_key` from the response to your frontend. The `client_key` is a short-lived token that lets your frontend operate on this specific Payment Intent without exposing your secret key.

***

## Step 2 — Collect card details and create a Payment Method (client-side)

On your **frontend**, use your **public API key** to create a Payment Method from the card details the customer enters. Never send card numbers to your backend.

```javascript
const response = await fetch('https://api.paymongo.com/v1/payment_methods', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('pk_test_YOUR_PUBLIC_KEY:')
  },
  body: JSON.stringify({
    data: {
      attributes: {
        type: 'card',
        details: {
          card_number: '4343434343434345',
          exp_month: 12,
          exp_year: 2030,
          cvc: '123'
        },
        billing: {
          name: 'Juan dela Cruz',
          email: 'juan@example.com',
          phone: '09171234567',
          address: {
            line1: '123 Main Street',
            city: 'Manila',
            state: 'Metro Manila',
            postal_code: '1000',
            country: 'PH'
          }
        }
      }
    }
  })
});
const paymentMethod = await response.json();
```

Save the Payment Method `id` from the response.

***

## Step 3 — Attach the Payment Method to the Payment Intent (client-side)

Still on your **frontend**, attach the Payment Method using the `client_key` from Step 1.

```javascript
const attachResponse = await fetch(
  `https://api.paymongo.com/v1/payment_intents/${paymentIntentId}/attach`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Basic ' + btoa('pk_test_YOUR_PUBLIC_KEY:')
    },
    body: JSON.stringify({
      data: {
        attributes: {
          payment_method: paymentMethodId,
          client_key: clientKey,
          return_url: 'https://yoursite.com/payment/complete'
        }
      }
    })
  }
);
const intent = await attachResponse.json();
```

***

## Step 4 — Handle the next action

Check the `status` in the response:

**`awaiting_next_action`** — 3D Secure authentication is required. Redirect the customer to the URL in `next_action.redirect.url`:

```javascript
if (intent.data.attributes.status === 'awaiting_next_action') {
  const redirectUrl = intent.data.attributes.next_action.redirect.url;
  window.location.href = redirectUrl;
}
```

After the customer completes 3DS authentication, they are redirected to your `return_url`. Retrieve the Payment Intent server-side using the `payment_intent_id` query parameter to check the final status.

**`succeeded`** — Payment is complete. No redirect needed.

**`awaiting_payment_method`** — An error occurred. Check `last_payment_error` for the reason and let the customer retry.

***

## Step 5 — Confirm success via webhook

In production, confirm payment outcomes via webhooks rather than relying solely on the redirect. Set up a webhook endpoint in your dashboard that listens for `payment.paid` and `payment.failed`.

When `payment.paid` fires, the `data.attributes.payment_intent_id` in the event body matches the Payment Intent ID from Step 1. Use this to fulfill the order on your end.

***

## What's next

* Add more payment methods: [E-wallets](e-wallets/index), [QR Ph](qr-ph/index), [BNPL](bnpl)
* Store cards for future purchases: [Card Vaulting](cards/card-vaulting)
* Set up recurring billing: [Subscriptions](payment-features/subscriptions)
* Go to production: [Best Practices](best-practices), [Testing](testing)