Implementation guides

Creating a payment intent

Qualy's API provides robust functionality for creating payments, allowing developers to implement a wide range of payment scenarios. This guide will take you through the process step by step, starting with a basic example and gradually introducing more complex payment scenarios.


Before you start

You need to have a Contact _id to create a Payment Intent, use the Contact API to create or retrieve a Contact.

Creating a payment

To create a payment on Qualy, you will have to use the Payment Intent API.

When you create the Payment Intent, you can specify options like the amount, currency, and more:

try {
  const response = await fetch('https://api.qualyhq.com/v1/payment-intents/create', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'ApiKey your-api-key-here',
      'X-TENANT-ID': 'your-tenant-id-here',
    },
    body: JSON.stringify({
      "intentType": "ad-hoc",
      "contact": "656b9ef1a3258074a705433b",
      "dueAt": "2025-05-10T14:26:07.369Z",
      "tax": "456b9ff1b3258074l705433b"
      "currency": "AUD",
      "items": [
        {
          "name": "Tuition fee",
          "description": "",
          "category": "Course",
          "amount": 100000
        },
        {
          "name": "Material fee",
          "description": "",
          "category": "Course",
          "amount": 10000
        },
        {
          "name": "Enrollment fee",
          "description": "",
          "category": "Course",
          "amount": 25000
        }
      ],
    }),
  });

  if (response.ok) {
    const data = await response.json();

    console.log(data);
  } else {
    throw new Error(`Request failed with status: ${response.status}`);
  }
} catch (error) {
  console.error(error);
}

Intent types

Payment intents can have different types. The intentType property helps customers in their reporting and analytics activities, and it's currently not used in any other feature. Make sure to select the correct intentType when creating a payment.

A quick note

While Qualy supports many types of intentType values, as a user of the API, you may probably want to use either ad-hoc or installment as other values are used for other purposes. If you believe you have a valid use-case, feel free to choose a different value.

Intent typeDescription
ad-hocFor payments that are not part of payment plan, such as specific one-off fees.
installmentFor payments part of a payment plan.
stepReserved use.
portalUsed by Qualy when a contact uses Qualy's to purchase a service from the Contact portal.
ecommerceUsed by Qualy when purchase is made via Qualy, and the contact didn't previously existed in the tenant's account.

Tax calculation

Qualy's v1 API calculates the payment's tax based on the total amount. If you need to apply different tax rates based on the payment item, you must create different payments.

Check our Tax API to retrieve, and create taxes. Use the created tax _id in the payment creation to get the tax calculated automatically by Qualy. Learn more about Tax calculation in our dedicated guide.

After the payment creation

After the payment is created, it is a best practice for your server to monitor webhooks to detect when the payment successfully completes or fails.

A PaymentIntent might have more than one Transaction object associated with it if there were multiple payment attempts, or if there were multiple partial payments. For each Transaction you can retrieve the status and details of the payment method used.

Sending payment reminders

Qualy will automatically send payment reminders via email and SMS based on the frequency selected using the Settings API. But if you want to send a payment reminder right away, you can use the Notifications API.

You will need the PaymentIntent _id and the the Contact_id to send the notification:

try {
  const response = await fetch('https://api.qualyhq.com/v1/notifications/queue/create', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'ApiKey your-api-key-here',
      'X-TENANT-ID': 'your-tenant-id-here',
    },
    body: JSON.stringify({
      "category": "payment-reminder",
      "comment": "",
      "data": {},
      "from": "user",
      "paymentIntent": "6634f56c7dbbc16e07b5025e",
      "recipientId": "6606ab8ffb9085579f1b5844",
      "recipientType": "contact",
      "templateId": "reminder"
    }),
  });

  if (response.ok) {
    const data = await response.json();

    console.log(data);
  } else {
    throw new Error(`Request failed with status: ${response.status}`);
  }
} catch (error) {
  console.error(error);
}
Previous
Errors