Migration guides

Migrating from Flywire

Flywire and Qualy solve the same problem: a student abroad paying an education provider in their own currency. Flywire's API is only open to selected partners, so many institutions work with it through its portal and reconciliation files. Qualy gives you the same flows through a public API, plus payouts to agents and partners on the same payment.


Concept map

FlywireQualyNotes
Student / payer recordContactThe student. Whoever actually pays (a parent, a sponsor) is the payer on the payment.
Payment request / invoicePayment intentWith line items, a dueAt and tax.
Payer portal / checkout linkPayment portal via links.short, or a reusable linkBranded with your subdomain or custom domain.
Paying in home currencysettlementCurrencyThe student pays in BRL, COP, INR… you receive your currency.
Payment plansOrders with installment payments, or financingFinancing covers buy-now-pay-later and card installments.
Payer identity checksBuilt into the portalQualy asks for what a method needs (e.g. CPF for PIX). Over the API you get a 424 listing what's missing.
Reconciliation fileWebhooks + queriesEach payment is reconciled as money arrives. No file to import.
Agent commission handled outside FlywirePayment splitsPay agents and partners from the same payment.
Refund requestRefund—

Payment requests → payment intents

Where you'd create a payment request (or upload a batch to Flywire), create a payment intent per student. Use your student or invoice number as number so your finance team sees the same reference:

const res = 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',
    number: 'STU-88231-T1',
    contact: 'maria.gomez@example.com',
    currency: 'AUD',
    dueAt: '2027-01-15T00:00:00.000Z',
    items: [
      { name: 'Tuition fee — Term 1', category: 'Course', amount: 820000 },
      { name: 'OSHC', category: 'Insurance', amount: 61000 },
    ],
  }),
});

const { data: payment } = await res.json();
console.log(payment.links.short); // what you'd send instead of the Flywire link

The student opens the link, picks a currency and a method available in their country, and pays. If they pay part now and the rest later, the payment moves to paid-partial and then paid-full.


Payment plans

A term fee split into instalments is an order with one installment payment per due date. Qualy chases each one when it falls overdue (see Dunning) and lets the student clear the remaining instalments early. If you'd rather a lender carries the plan, offer financing on the portal.


Agents and partners

With Flywire you typically receive the full amount and pay the agent's commission separately. In Qualy you attach the split when you create the payment, and the commission is paid out when the student's money settles:

body: JSON.stringify({
  type: 'keep-percentage',
  currency: 'AUD',
  amount: 697000, // what the school receives
  keep: 123000,   // what the agent (you) keeps
  partnership: 'usyd',
  contact: 'maria.gomez@example.com',
  paymentIntent: '661e9bbfe0eb901d6b2f2670',
  item: '661e9bc0e0eb901d6b2f2682',
}),

See Creating payment splits for every split type and how to preview payouts before you commit.


Reconciliation

Instead of downloading a reconciliation file, listen for:

  • paymentIntents.update — the payment's status changed (paid-partial, paid-full, overdue…).
  • transactions.create — money arrived (or was refunded), with amount, currency and method.
  • splitIntents.update — a partner's payout moved.

See Setting up webhooks. For a one-off backfill, page through GET /v1/payment-intents with query filters.

Moving open payments

Let payments already issued through Flywire finish there. Start new payment requests in Qualy from a cut-off date, so no student receives two links for the same fee.

Previous
From Airwallex