Skip to content

Cantilapay phase-2

Cantilapay lets your application accept payments through a single, Stripe-shaped API. Under the hood it is Cantila-owned and built on Adyen for Platforms — but you never touch Adyen directly. You call one SDK, @cantila/cantilapay, and Cantila handles the platform orchestration.

The shape will feel familiar if you have ever used Stripe: customers, payment intents, payment methods, subscriptions, products, prices, invoices, refunds, checkout sessions, a billing portal, payouts, balance, tax, and webhooks. The names and lifecycles are deliberately close.

What works today. Cantilapay is early. Build and test everything in test mode first — create a Cantilapay account, complete onboarding for test, and run the full payment lifecycle against test cards. Live mode unlocks per account once KYC for live is approved. Treat the API as stable in shape but expanding in coverage.

Tenant as merchant of record

In Cantilapay, your Cantila tenant is the merchant of record (MoR). Funds settle to your connected account; Cantila orchestrates the platform and takes a platform fee (surfaced as platformFeeBps on your account and platformFeeAmount on each payment intent). This is the "platform model" — you onboard once, then transact under your own merchant identity.

Test vs live mode

Every object carries a mode of test or live. Your API key is scoped to one mode, so you never mix test and live data:

ModeKey prefixPurpose
testcsk_test_…Build and verify with test cards. No real money moves.
livecsk_live_…Real charges. Requires approved live onboarding.

Your account exposes testReady and liveReady booleans so you can check which modes are usable before you transact.

Onboarding (KYC)

Before you can charge in a given mode, the account must complete hosted KYC. Generate a one-time onboarding link and redirect the merchant to it:

import { Cantilapay } from "@cantila/cantilapay";

const cp = new Cantilapay(process.env.CANTILAPAY_SECRET_KEY!);

const { url, expiresAt } = await cp.accounts.onboardingLink({
  mode: "test",
  country: "US",
  returnUrl: "https://app.example.com/settings/payments",
});

// Redirect the merchant to `url`; they return to `returnUrl` when done.

When they return, check the account status:

const account = await cp.accounts.retrieve();
console.log(account.status);     // "created" | "onboarding" | "active" | "rejected" | "disabled"
console.log(account.testReady);  // true once test KYC is approved
console.log(account.liveReady);  // true once live KYC is approved

Where keys come from

Your Cantilapay secret key is a bearer secret. Issue it from the Cantila Console under your tenant's Cantilapay settings, then store it in an environment variable — never in client-side code or version control:

export CANTILAPAY_SECRET_KEY="csk_test_..."

The SDK reads nothing implicitly — you pass the key explicitly to the constructor (see the quickstart). Use a test key during development and swap to a live key only in production.

Amounts are minor units

All amounts are integer minor units of the currency. 1000 in usd means $10.00. There are no floats and no decimal amounts anywhere in the API.

Next steps

  • Quickstart — install, construct the client, and take your first payment.
  • SDK reference — every resource, method, error, and enum.
  • Webhooks — receive and verify events.