Documentation

Mandates

Mandates

A mandate is a customer's authorization for you to charge their payment method on a recurring basis. Mandates are the foundation for subscriptions, installment plans, and any flow where you charge a saved payment method without the customer being present for each transaction.

How Mandates Work

  1. The customer authorizes a mandate during the first payment
  2. PerfectPay records the mandate and associates it with the customer's payment method
  3. Subsequent charges reference the mandate, allowing payment confirmation without additional customer interaction
  4. The customer or merchant can revoke the mandate at any time

Setting Up a Mandate

Create a mandate by including the mandate_data field when creating a payment:

POST /payments

GET //sandbox.perfectpay.ai/payments
curl https://sandbox.perfectpay.ai/payments \
  -X POST \
  -H "api-key: YOUR_SECRET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4999,
    "currency": "USD",
    "customer_id": "cus_abc123",
    "confirm": true,
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
      "card": {
        "card_number": "4242424242424242",
        "card_exp_month": "10",
        "card_exp_year": "25",
        "card_cvc": "123",
        "card_holder_name": "Jane Doe"
      }
    },
    "mandate_data": {
      "customer_acceptance": {
        "acceptance_type": "online",
        "online": {
          "ip_address": "203.0.113.42",
          "user_agent": "Mozilla/5.0"
        }
      },
      "mandate_type": {
        "multi_use": {
          "amount": 4999,
          "currency": "USD"
        }
      }
    },
    "setup_future_usage": "off_session",
    "return_url": "https://example.com/checkout/complete"
  }'

The response includes a mandate_id that you use for subsequent charges.

Charging Against a Mandate

Once a mandate is established, charge the customer's saved payment method without requiring them to be present:

GET //sandbox.perfectpay.ai/payments
curl https://sandbox.perfectpay.ai/payments \
  -X POST \
  -H "api-key: YOUR_SECRET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4999,
    "currency": "USD",
    "customer_id": "cus_abc123",
    "confirm": true,
    "off_session": true,
    "mandate_id": "man_abc123",
    "payment_method_id": "pm_abc123",
    "return_url": "https://example.com/checkout/complete"
  }'

List Mandates

GET /mandates/list

GET //sandbox.perfectpay.ai/mandates/list
curl https://sandbox.perfectpay.ai/mandates/list \
  -H "api-key: YOUR_SECRET_API_KEY"

Retrieve a Mandate

GET /mandates/{mandate_id}

GET //sandbox.perfectpay.ai/mandates/man_abc123
curl https://sandbox.perfectpay.ai/mandates/man_abc123 \
  -H "api-key: YOUR_SECRET_API_KEY"

Revoke a Mandate

POST /mandates/revoke/{mandate_id}

Revoking a mandate prevents any future charges against it. Existing completed payments are not affected.

GET //sandbox.perfectpay.ai/mandates/revoke/man_abc123
curl https://sandbox.perfectpay.ai/mandates/revoke/man_abc123 \
  -X POST \
  -H "api-key: YOUR_SECRET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Mandate Types

TypeDescription
single_useAuthorizes exactly one future charge
multi_useAuthorizes multiple future charges up to the specified amount and currency

Mandates and Subscriptions

The Subscriptions API uses mandates internally. When a customer subscribes, PerfectPay creates a mandate automatically so that recurring billing charges can proceed without customer interaction on each cycle.

If you are building custom recurring billing logic instead of using the subscriptions API, set up mandates directly using the flow described above.

Operational Notes

  • Always capture customer acceptance data (ip_address, user_agent) when creating a mandate -- this is required for regulatory compliance
  • Set setup_future_usage to "off_session" on the initial payment so the payment method is saved for later use
  • Monitor active mandates in the dashboard and revoke any that are no longer needed
  • Use Webhooks to track mandate status changes