Docs
BlogHomeStart building

Payments (totalum-sdk/payments)


import … from 'totalum-sdk/payments' — or the same namespace on totalum from 'totalum-sdk'. Install, configuration and errors: Totalum SDK.

Take payments and subscriptions with Stripe on the project owner's own Stripe account (Stripe Connect), without handling card data: create a hosted Checkout, send the buyer to its url, and read the result back. The owner connects Stripe once with onboardingLink(). The preview and the sandbox use Stripe test mode; the published site uses live mode once the owner switched it on. Payment events reach the app's own POST /api/webhooks/stripe with no setup, signed by Totalum (verify them with totalum.webhooks.verify).

ts
const { url } = await totalum.payments.createCheckout({
  mode: 'payment',
  lineItems: [{ name: 'Pro plan', unitAmount: 1900, currency: 'eur', quantity: 1 }],
  successUrl: 'https://acme.totalum.app/thanks?session_id={CHECKOUT_SESSION_ID}',
  cancelUrl: 'https://acme.totalum.app/pricing',
});
Method or typeWhat it does
totalumPaymentsCreates the payments namespace (the same object as totalum.payments, scope payments): Stripe Connect charges on the project's own connected account.
payments.getStatusWhether the project's Stripe account can take payments right now: use it to show "Connect Stripe" to the owner or to hide a Buy button while payments are off.
payments.onboardingLinkA single-use link to Stripe's hosted onboarding, where the project owner connects (or updates) the Stripe account the app's payments go to.
payments.createCheckoutCreates a Stripe Checkout page for a one-off payment (payment), a subscription (subscription) or saving a card for later (setup), and returns its URL: redirect the buyer there.
payments.getCheckoutReads a Checkout Session back, to confirm a payment on the page Stripe returns the buyer to (successUrl with ?session_id={CHECKOUT_SESSION_ID}): when paymentStatus is 'paid', mark the order paid — no webhook needed.
payments.customerPortalLinkA link to Stripe's hosted customer portal, where a subscriber updates their card, downloads invoices or cancels their subscription.
payments.subscriptions.getReads a subscription: give access while status is 'active' or 'trialing'; currentPeriodEnd is the next renewal (or the end of access when cancelAtPeriodEnd is true).
payments.subscriptions.updateCancels a subscription at the end of the paid period (cancelAtPeriodEnd: true, the usual "Cancel" button: the member keeps access until then), or undoes that (false).
payments.subscriptions.cancelCancels a subscription immediately: no more charges, status: 'canceled' at once, access ends now.
payments.refunds.createRefunds a payment, in full or in part.
CheckoutInputWhat a Checkout page sells and where it sends the buyer, for payments.createCheckout().
CheckoutOutputThe Checkout page created by payments.createCheckout().
CheckoutSessionA Checkout Session read back with payments.getCheckout().
CustomerPortalLinkInputThe input of payments.customerPortalLink().
CustomerPortalLinkOutputThe answer of payments.customerPortalLink().
OnboardingLinkInputThe input of payments.onboardingLink().
OnboardingLinkOutputThe answer of payments.onboardingLink().
PaymentsStatusThe state of the project's Stripe account, from payments.getStatus().
RefundInputThe input of payments.refunds.create().
RefundOutputA refund, from payments.refunds.create().
SubscriptionA Stripe subscription, from payments.subscriptions.*.
SubscriptionUpdateInputThe change payments.subscriptions.update() makes.

#totalumPayments

ts
totalumPayments(options?: TotalumClientOptions): TotalumPayments

Creates the payments namespace (the same object as totalum.payments, scope payments): Stripe Connect charges on the project's own connected account. Card data never passes through here — send buyers to the hosted Checkout url; card fields are refused with CARD_DATA_NOT_ACCEPTED. Stripe test mode on the preview and in the sandbox; live mode only on the published site, once the owner onboarded and switched live on. Payment events (payments.<Stripe type>) reach the app's own POST /api/webhooks/stripe with no setup — test mode's on the preview, live mode's on the published site — signed by Totalum: verify them with totalum.webhooks.verify.

Parameters

NameTypeRequiredDescription
optionsTotalumClientOptionsnoThe project key, API URL and environment; each falls back to its environment variable.
options.keystringnoProject key tlm_pk_…; default TOTALUM_PROJECT_KEY. Server-side only.
options.apiUrlstringnoThe Totalum API's URL: default TOTALUM_SDK_API_URL, else https://sdk-api.totalum.app.
options.env'dev' | 'live'noSent as x-totalum-env on every call (the database it targets, and dev vs live usage); default TOTALUM_ENV, else live.

Returns TotalumPayments — The payments namespace: the methods below.

Example

ts
import { totalumPayments } from 'totalum-sdk/payments';

const payments = totalumPayments();
const status = await payments.getStatus();

The namespace's type is exported as TotalumPayments (import type { TotalumPayments } from 'totalum-sdk/payments').

#payments.getStatus

ts
payments.getStatus(): Promise<PaymentsStatus>

Whether the project's Stripe account can take payments right now: use it to show "Connect Stripe" to the owner or to hide a Buy button while payments are off. Free.

Returns Promise<PaymentsStatus> — The state of the connected Stripe account in the current mode (test on the preview, live on the published site).

FieldTypeAlways presentDescription
enabledbooleanyesWhether payments can be used in the current mode.
mode'connect' | 'own_key'yesconnect: payments run on the owner's Stripe account connected through Totalum. own_key: the app uses its own Stripe keys.
accountIdstring | nullyesThe connected Stripe account id (acct_…), or null before the first connection.
livemodebooleanyesWhether this is the live (real money) account; false on the preview and in the sandbox.
chargesEnabledbooleanyesWhether the account can take payments now.
payoutsEnabledbooleanyesWhether Stripe can pay out to the owner's bank account.
detailsSubmittedbooleanyesWhether the owner finished Stripe's onboarding form.
requirements{ currentlyDue, pastDue, eventuallyDue }yesWhat Stripe still needs from the owner.
requirements.currentlyDuestring[]yesInformation Stripe needs now to keep the account working.
requirements.pastDuestring[]yesInformation that is overdue: charges or payouts may be paused until it is given.
requirements.eventuallyDuestring[]yesInformation Stripe will need later.
liveEnabledbooleanyesWhether the owner switched live payments on for the published site.
disconnectedAtstring | nullnoWhen the owner disconnected the Stripe account, or null.

Errors — besides the errors every call can throw:

CodeHTTPWhen
PAYMENTS_NOT_ENABLED403Payments are not configured for this environment.

Example

ts
const status = await totalum.payments.getStatus();
if (!status.chargesEnabled) return <p>Payments are not set up yet.</p>;

Result:

json
{
  "enabled": true,
  "mode": "connect",
  "accountId": "acct_1QZ3kPQm4n8Xa2Lb",
  "livemode": true,
  "chargesEnabled": true,
  "payoutsEnabled": true,
  "detailsSubmitted": true,
  "requirements": { "currentlyDue": [], "pastDue": [], "eventuallyDue": [] },
  "liveEnabled": true,
  "disconnectedAt": null
}
ts
payments.onboardingLink(input: OnboardingLinkInput): Promise<OnboardingLinkOutput>

A single-use link to Stripe's hosted onboarding, where the project owner connects (or updates) the Stripe account the app's payments go to. Only for the owner: the coding agent's sandbox key is refused. The live account can only be connected once the project is published.

Parameters

NameTypeRequiredDescription
inputOnboardingLinkInputyesWhere Stripe sends the owner back, and the account's country.
input.returnUrlstringyesWhere Stripe sends the owner after onboarding. Allowed: a URL.
input.refreshUrlstringyesWhere Stripe sends the owner if the link expired or was already used; make a new link there. Allowed: a URL.
input.type'account_onboarding' | 'account_update'noaccount_onboarding (default) to connect the account, account_update to change its details.
input.countrystringnoThe two-letter country of the owner's business (ES, US); required the first time the live account is created.

Returns Promise<OnboardingLinkOutput> — The onboarding URL to redirect the owner to, and when it expires.

FieldTypeAlways presentDescription
urlstringyesThe Stripe onboarding page to redirect the owner to (single use).
expiresAtstringyesWhen the link stops working.

Errors — besides the errors every call can throw:

CodeHTTPWhen
PAYMENTS_PUBLISH_FIRST409The project is not published yet: publish it, then connect Stripe.
MISSING_INPUT400country is needed to create the live Stripe account.
FORBIDDEN_SCOPE403Called with the agent's sandbox key: onboarding links are for the project owner.
STRIPE_ERROR400Stripe refused the request; details.stripeCode says why.

Example

ts
const { url } = await totalum.payments.onboardingLink({
  returnUrl: 'https://acme.totalum.app/admin/payments?connected=1',
  refreshUrl: 'https://acme.totalum.app/admin/payments',
  country: 'ES',
});

Result:

json
{ "url": "https://connect.stripe.com/setup/e/acct_1QZ3kPQm4n8Xa2Lb/Xq3VbD9yPpLk", "expiresAt": "2026-10-11T18:05:00.000Z" }

#payments.createCheckout

ts
payments.createCheckout(input: CheckoutInput): Promise<CheckoutOutput>

Creates a Stripe Checkout page for a one-off payment (payment), a subscription (subscription) or saving a card for later (setup), and returns its URL: redirect the buyer there. Put your own ids (order, user) in metadata to find them again on the return page or in the webhook. A subscription needs a recurring price: an inline item with recurring: { interval: 'month' }, or a priceId; its metadata is also set on the subscription.

Parameters

NameTypeRequiredDescription
inputCheckoutInputyesWhat is sold, the mode, and where Stripe sends the buyer afterwards.
input.mode'payment' | 'subscription' | 'setup'yespayment: a one-off payment. subscription: a recurring payment (needs a recurring price). setup: save a card without charging.
input.successUrlstringyesWhere Stripe sends the buyer after paying. Add ?session_id={CHECKOUT_SESSION_ID} to read the session back with getCheckout(). Allowed: a URL.
input.cancelUrlstringyesWhere Stripe sends the buyer if they go back without paying. Allowed: a URL.
input.lineItems({ priceId, quantity } | { name, unitAmount, currency, quantity, recurring? })[]noWhat is sold: each item is either a Stripe priceId with a quantity, or an inline item (name, unitAmount, currency, quantity, optional recurring). Required for payment and subscription. Allowed: at least 1 item.
input.lineItems.priceIdstringnoA Price id (price_…) of the connected Stripe account, instead of an inline item. Allowed: at least 1 character.
input.lineItems.quantitynumberyesHow many units. Allowed: > 0.
input.lineItems.namestringnoThe product name shown on the Checkout page (inline item). Allowed: at least 1 character.
input.lineItems.unitAmountnumbernoThe price of one unit in the smallest currency unit: cents for EUR/USD (1900 = 19.00). Allowed: > 0.
input.lineItems.currencystringnoThree-letter ISO currency code, lower case (eur, usd). Allowed: exactly 3 characters.
input.lineItems.recurring{ interval, intervalCount? }noMakes the inline item a subscription price: how often it renews.
input.lineItems.recurring.interval'day' | 'month' | 'week' | 'year'yesThe billing period: day, week, month or year.
input.lineItems.recurring.intervalCountnumbernoHow many periods between charges (3 with month = quarterly). Default 1. Allowed: > 0.
input.currencystringnoThe currency of a setup session (three-letter code, lower case). Allowed: exactly 3 characters.
input.customerEmailstringnoPre-fills the buyer's e-mail on the Checkout page. Allowed: an e-mail address.
input.customerIdstringnoAn existing Stripe customer (cus_…) to charge, so their saved cards appear.
input.metadataRecord<string, string>noYour own key/value strings (order id, user id). Returned by getCheckout(), in the webhook events and, for a subscription, set on the subscription.
input.allowPromotionCodesbooleannotrue shows a promotion-code field.
input.automaticTaxbooleannotrue lets Stripe Tax compute tax (the owner must have Stripe Tax set up).
input.trialDaysnumbernoFree trial days before the first charge of a subscription. Allowed: > 0.
input.clientReferenceIdstringnoOne more id of yours, returned by getCheckout().

Returns Promise<CheckoutOutput> — The Checkout Session id and the URL to redirect the buyer to.

FieldTypeAlways presentDescription
idstringyesThe Checkout Session id (cs_test_… or cs_live_…).
urlstringyesThe Stripe Checkout page: redirect the buyer here.

Errors — besides the errors every call can throw:

CodeHTTPWhen
CARD_DATA_NOT_ACCEPTED400The request contained card fields: card data is only ever typed on Stripe's page.
PAYMENTS_LIVE_ONBOARDING_REQUIRED403Live mode, but the owner has not finished Stripe onboarding.
PAYMENTS_ACCOUNT_DISCONNECTED403The owner disconnected the Stripe account: they must connect it again.
PAYMENTS_NOT_ENABLED403Payments are not configured for this environment.
STRIPE_ERROR400Stripe refused the session (an unknown priceId, a bad currency); details.stripeCode.
STRIPE_RATE_LIMITED429Stripe's own rate limit; retry shortly.

Examples

ts
// src/app/api/checkout/route.ts
const { url } = await totalum.payments.createCheckout({
  mode: 'payment',
  lineItems: [{ name: 'Concert ticket', unitAmount: 2500, currency: 'eur', quantity: 2 }],
  successUrl: 'https://acme.totalum.app/orders/ord_42?session_id={CHECKOUT_SESSION_ID}',
  cancelUrl: 'https://acme.totalum.app/cart',
  customerEmail: 'ana@example.com',
  metadata: { orderId: 'ord_42' },
});
return Response.redirect(url, 303);

Result:

json
{ "id": "cs_test_a1B2c3D4e5F6g7H8i9J0", "url": "https://checkout.stripe.com/c/pay/cs_test_a1B2c3D4e5F6g7H8i9J0#fid…" }
ts
// a monthly subscription with a 14-day trial
const { url } = await totalum.payments.createCheckout({
  mode: 'subscription',
  lineItems: [{ name: 'Pro', unitAmount: 1900, currency: 'eur', quantity: 1, recurring: { interval: 'month' } }],
  trialDays: 14,
  successUrl: 'https://acme.totalum.app/billing?session_id={CHECKOUT_SESSION_ID}',
  cancelUrl: 'https://acme.totalum.app/pricing',
  metadata: { userId: user.id },
});

#payments.getCheckout

ts
payments.getCheckout(sessionId: string): Promise<CheckoutSession>

Reads a Checkout Session back, to confirm a payment on the page Stripe returns the buyer to (successUrl with ?session_id={CHECKOUT_SESSION_ID}): when paymentStatus is 'paid', mark the order paid — no webhook needed. A subscription checkout also gives subscriptionId and customerId: store both on the member.

Parameters

NameTypeRequiredDescription
sessionIdstringyesThe session_id Stripe added to successUrl (cs_test_… or cs_live_…).

Returns Promise<CheckoutSession> — The session's status, amount, your metadata and the ids it created.

FieldTypeAlways presentDescription
idstringyesThe Checkout Session id.
status'expired' | 'open' | 'complete'yesopen: not finished. complete: the buyer finished. expired: abandoned (sessions expire after 24 h).
paymentStatus'paid' | 'unpaid' | 'no_payment_required'yespaid: the money was taken (mark the order paid). unpaid: not yet (some payment methods confirm later). no_payment_required: nothing to pay (a setup session or a 100 % discount).
amountTotalnumber | nullyesThe total charged, in the smallest currency unit (5000 = 50.00).
currencystring | nullyesThe currency, lower case.
metadataRecord<string, string>yesThe metadata you passed to createCheckout().
paymentIntentIdstring | nullyesThe payment (pi_…) of a payment session; pass it to refunds.create().
customerEmailstring | nullyesThe e-mail the buyer typed.
clientReferenceIdstring | nullyesThe clientReferenceId you passed.
customerIdstring | nullyesThe Stripe customer (cus_…) of a subscription or saved card; store it for customerPortalLink().
subscriptionIdstring | nullyesThe subscription (sub_…) a subscription session created; store it to check access later.

Errors — besides the errors every call can throw:

CodeHTTPWhen
VALIDATION_ERROR400Not a Checkout Session id.
STRIPE_ERROR404No such session on this project's Stripe account.

Example

ts
// src/app/orders/[id]/page.tsx
const session = await totalum.payments.getCheckout(searchParams.session_id);
if (session.paymentStatus === 'paid') await markOrderPaid(session.metadata.orderId);

Result:

json
{
  "id": "cs_test_a1B2c3D4e5F6g7H8i9J0",
  "status": "complete",
  "paymentStatus": "paid",
  "amountTotal": 5000,
  "currency": "eur",
  "metadata": { "orderId": "ord_42" },
  "paymentIntentId": "pi_3QZ4mNPQm4n8Xa2L0x1y2z3a",
  "customerEmail": "ana@example.com",
  "clientReferenceId": null,
  "customerId": null,
  "subscriptionId": null
}
ts
payments.customerPortalLink(input: CustomerPortalLinkInput): Promise<CustomerPortalLinkOutput>

A link to Stripe's hosted customer portal, where a subscriber updates their card, downloads invoices or cancels their subscription. Show it as "Manage billing".

Parameters

NameTypeRequiredDescription
inputCustomerPortalLinkInputyesThe Stripe customer and where to send them back.
input.customerIdstringyesThe Stripe customer (cus_…), from getCheckout(). Allowed: at least 1 character.
input.returnUrlstringyesWhere the portal's back link goes. Allowed: a URL.

Returns Promise<CustomerPortalLinkOutput> — The portal URL to redirect the customer to.

FieldTypeAlways presentDescription
urlstringyesThe portal page to redirect the customer to.

Errors — besides the errors every call can throw:

CodeHTTPWhen
STRIPE_ERROR404No such customer on this project's Stripe account.
PAYMENTS_LIVE_ONBOARDING_REQUIRED403Live mode, but the owner has not finished Stripe onboarding.

Example

ts
const { url } = await totalum.payments.customerPortalLink({
  customerId: member.stripeCustomerId,
  returnUrl: 'https://acme.totalum.app/account',
});

Result:

json
{ "url": "https://billing.stripe.com/p/session/test_YWNjdF8xUVozaw…" }

#payments.subscriptions.get

ts
payments.subscriptions.get(subscriptionId: string): Promise<Subscription>

Reads a subscription: give access while status is 'active' or 'trialing'; currentPeriodEnd is the next renewal (or the end of access when cancelAtPeriodEnd is true).

Parameters

NameTypeRequiredDescription
subscriptionIdstringyesThe subscription id (sub_…) from getCheckout() or a payment webhook.

Returns Promise<Subscription> — The subscription's status, renewal date and metadata.

FieldTypeAlways presentDescription
idstringyesThe subscription id (sub_…).
status'unpaid' | 'active' | 'paused' | 'incomplete' | 'incomplete_expired' | 'trialing' | 'past_due' | 'canceled'yesGive access while active or trialing. past_due/unpaid: a renewal failed. canceled: ended. incomplete/incomplete_expired: the first payment did not go through. paused: a trial ended without a payment method.
customerIdstringyesThe Stripe customer (cus_…).
cancelAtPeriodEndbooleanyestrue when it ends at currentPeriodEnd instead of renewing.
currentPeriodEndstring | nullyesWhen the paid period ends: the next renewal, or the end of access when cancelAtPeriodEnd.
canceledAtstring | nullyesWhen it was canceled, or null.
metadataRecord<string, string>yesThe metadata given to the Checkout that created it.

Errors — besides the errors every call can throw:

CodeHTTPWhen
VALIDATION_ERROR400Not a subscription id.
STRIPE_ERROR404No such subscription on this project's Stripe account.

Example

ts
const sub = await totalum.payments.subscriptions.get(member.subscriptionId);
const active = sub.status === 'active' || sub.status === 'trialing';

Result:

json
{
  "id": "sub_1QZ5aBPQm4n8Xa2LcD3eF4gH",
  "status": "active",
  "customerId": "cus_R2x9YpL0aBcDeF",
  "cancelAtPeriodEnd": false,
  "currentPeriodEnd": "2026-11-11T17:40:00.000Z",
  "canceledAt": null,
  "metadata": { "userId": "user_42" }
}

#payments.subscriptions.update

ts
payments.subscriptions.update(subscriptionId: string, input: SubscriptionUpdateInput): Promise<Subscription>

Cancels a subscription at the end of the paid period (cancelAtPeriodEnd: true, the usual "Cancel" button: the member keeps access until then), or undoes that (false).

Parameters

NameTypeRequiredDescription
subscriptionIdstringyesThe subscription id (sub_…).
inputSubscriptionUpdateInputyesWhether it ends at the end of the period.
input.cancelAtPeriodEndbooleanyestrue: end the subscription when the paid period ends. false: keep renewing (undo a cancellation).

Returns Promise<Subscription> — The updated subscription.

FieldTypeAlways presentDescription
idstringyesThe subscription id (sub_…).
status'unpaid' | 'active' | 'paused' | 'incomplete' | 'incomplete_expired' | 'trialing' | 'past_due' | 'canceled'yesGive access while active or trialing. past_due/unpaid: a renewal failed. canceled: ended. incomplete/incomplete_expired: the first payment did not go through. paused: a trial ended without a payment method.
customerIdstringyesThe Stripe customer (cus_…).
cancelAtPeriodEndbooleanyestrue when it ends at currentPeriodEnd instead of renewing.
currentPeriodEndstring | nullyesWhen the paid period ends: the next renewal, or the end of access when cancelAtPeriodEnd.
canceledAtstring | nullyesWhen it was canceled, or null.
metadataRecord<string, string>yesThe metadata given to the Checkout that created it.

Errors — besides the errors every call can throw:

CodeHTTPWhen
VALIDATION_ERROR400Not a subscription id.
STRIPE_ERROR404No such subscription on this project's Stripe account.

Example

ts
const sub = await totalum.payments.subscriptions.update(member.subscriptionId, { cancelAtPeriodEnd: true });

Result:

json
{
  "id": "sub_1QZ5aBPQm4n8Xa2LcD3eF4gH",
  "status": "active",
  "customerId": "cus_R2x9YpL0aBcDeF",
  "cancelAtPeriodEnd": true,
  "currentPeriodEnd": "2026-11-11T17:40:00.000Z",
  "canceledAt": null,
  "metadata": { "userId": "user_42" }
}

#payments.subscriptions.cancel

ts
payments.subscriptions.cancel(subscriptionId: string): Promise<Subscription>

Cancels a subscription immediately: no more charges, status: 'canceled' at once, access ends now. To let the member keep the period they paid for, use update(id, { cancelAtPeriodEnd: true }) instead.

Parameters

NameTypeRequiredDescription
subscriptionIdstringyesThe subscription id (sub_…).

Returns Promise<Subscription> — The canceled subscription.

FieldTypeAlways presentDescription
idstringyesThe subscription id (sub_…).
status'unpaid' | 'active' | 'paused' | 'incomplete' | 'incomplete_expired' | 'trialing' | 'past_due' | 'canceled'yesGive access while active or trialing. past_due/unpaid: a renewal failed. canceled: ended. incomplete/incomplete_expired: the first payment did not go through. paused: a trial ended without a payment method.
customerIdstringyesThe Stripe customer (cus_…).
cancelAtPeriodEndbooleanyestrue when it ends at currentPeriodEnd instead of renewing.
currentPeriodEndstring | nullyesWhen the paid period ends: the next renewal, or the end of access when cancelAtPeriodEnd.
canceledAtstring | nullyesWhen it was canceled, or null.
metadataRecord<string, string>yesThe metadata given to the Checkout that created it.

Errors — besides the errors every call can throw:

CodeHTTPWhen
VALIDATION_ERROR400Not a subscription id.
STRIPE_ERROR404No such subscription on this project's Stripe account.

Example

ts
const sub = await totalum.payments.subscriptions.cancel('sub_1QZ5aBPQm4n8Xa2LcD3eF4gH');

Result:

json
{
  "id": "sub_1QZ5aBPQm4n8Xa2LcD3eF4gH",
  "status": "canceled",
  "customerId": "cus_R2x9YpL0aBcDeF",
  "cancelAtPeriodEnd": false,
  "currentPeriodEnd": "2026-11-11T17:40:00.000Z",
  "canceledAt": "2026-10-11T18:02:11.000Z",
  "metadata": { "userId": "user_42" }
}

#payments.refunds.create

ts
payments.refunds.create(input: RefundInput): Promise<RefundOutput>

Refunds a payment, in full or in part. The buyer gets the money back on their card in a few days.

Parameters

NameTypeRequiredDescription
inputRefundInputyesThe payment to refund and, for a partial refund, how much.
input.paymentIntentIdstringyesThe payment to refund (pi_…), from getCheckout() or a payment webhook. Allowed: at least 1 character.
input.amountnumbernoFor a partial refund, the amount in the smallest currency unit. Default: everything not yet refunded. Allowed: > 0.
input.reason'duplicate' | 'fraudulent' | 'requested_by_customer'noWhy, as Stripe records it: duplicate, fraudulent or requested_by_customer.

Returns Promise<RefundOutput> — The refund's id, status and amount.

FieldTypeAlways presentDescription
idstringyesThe refund id (re_…).
statusstringyesStripe's status: succeeded, pending, requires_action, failed or canceled.
amountnumberyesThe refunded amount in the smallest currency unit.
currencystringyesThe currency, lower case.

Errors — besides the errors every call can throw:

CodeHTTPWhen
STRIPE_ERROR400Stripe refused it (already refunded, an amount above what is left); details.stripeCode.
PAYMENTS_LIVE_ONBOARDING_REQUIRED403Live mode, but the owner has not finished Stripe onboarding.

Example

ts
const refund = await totalum.payments.refunds.create({
  paymentIntentId: 'pi_3QZ4mNPQm4n8Xa2L0x1y2z3a',
  amount: 2500,
  reason: 'requested_by_customer',
});

Result:

json
{ "id": "re_3QZ6bCPQm4n8Xa2L1k2l3m4n", "status": "succeeded", "amount": 2500, "currency": "eur" }

#CheckoutInput

What a Checkout page sells and where it sends the buyer, for payments.createCheckout().

NameTypeRequiredDescription
mode'payment' | 'subscription' | 'setup'yespayment: a one-off payment. subscription: a recurring payment (needs a recurring price). setup: save a card without charging.
successUrlstringyesWhere Stripe sends the buyer after paying. Add ?session_id={CHECKOUT_SESSION_ID} to read the session back with getCheckout(). Allowed: a URL.
cancelUrlstringyesWhere Stripe sends the buyer if they go back without paying. Allowed: a URL.
lineItems({ priceId, quantity } | { name, unitAmount, currency, quantity, recurring? })[]noWhat is sold: each item is either a Stripe priceId with a quantity, or an inline item (name, unitAmount, currency, quantity, optional recurring). Required for payment and subscription. Allowed: at least 1 item.
lineItems.priceIdstringnoA Price id (price_…) of the connected Stripe account, instead of an inline item. Allowed: at least 1 character.
lineItems.quantitynumberyesHow many units. Allowed: > 0.
lineItems.namestringnoThe product name shown on the Checkout page (inline item). Allowed: at least 1 character.
lineItems.unitAmountnumbernoThe price of one unit in the smallest currency unit: cents for EUR/USD (1900 = 19.00). Allowed: > 0.
lineItems.currencystringnoThree-letter ISO currency code, lower case (eur, usd). Allowed: exactly 3 characters.
lineItems.recurring{ interval, intervalCount? }noMakes the inline item a subscription price: how often it renews.
lineItems.recurring.interval'day' | 'month' | 'week' | 'year'yesThe billing period: day, week, month or year.
lineItems.recurring.intervalCountnumbernoHow many periods between charges (3 with month = quarterly). Default 1. Allowed: > 0.
currencystringnoThe currency of a setup session (three-letter code, lower case). Allowed: exactly 3 characters.
customerEmailstringnoPre-fills the buyer's e-mail on the Checkout page. Allowed: an e-mail address.
customerIdstringnoAn existing Stripe customer (cus_…) to charge, so their saved cards appear.
metadataRecord<string, string>noYour own key/value strings (order id, user id). Returned by getCheckout(), in the webhook events and, for a subscription, set on the subscription.
allowPromotionCodesbooleannotrue shows a promotion-code field.
automaticTaxbooleannotrue lets Stripe Tax compute tax (the owner must have Stripe Tax set up).
trialDaysnumbernoFree trial days before the first charge of a subscription. Allowed: > 0.
clientReferenceIdstringnoOne more id of yours, returned by getCheckout().

#CheckoutOutput

The Checkout page created by payments.createCheckout().

FieldTypeAlways presentDescription
idstringyesThe Checkout Session id (cs_test_… or cs_live_…).
urlstringyesThe Stripe Checkout page: redirect the buyer here.

#CheckoutSession

A Checkout Session read back with payments.getCheckout().

FieldTypeAlways presentDescription
idstringyesThe Checkout Session id.
status'expired' | 'open' | 'complete'yesopen: not finished. complete: the buyer finished. expired: abandoned (sessions expire after 24 h).
paymentStatus'paid' | 'unpaid' | 'no_payment_required'yespaid: the money was taken (mark the order paid). unpaid: not yet (some payment methods confirm later). no_payment_required: nothing to pay (a setup session or a 100 % discount).
amountTotalnumber | nullyesThe total charged, in the smallest currency unit (5000 = 50.00).
currencystring | nullyesThe currency, lower case.
metadataRecord<string, string>yesThe metadata you passed to createCheckout().
paymentIntentIdstring | nullyesThe payment (pi_…) of a payment session; pass it to refunds.create().
customerEmailstring | nullyesThe e-mail the buyer typed.
clientReferenceIdstring | nullyesThe clientReferenceId you passed.
customerIdstring | nullyesThe Stripe customer (cus_…) of a subscription or saved card; store it for customerPortalLink().
subscriptionIdstring | nullyesThe subscription (sub_…) a subscription session created; store it to check access later.

#CustomerPortalLinkInput

The input of payments.customerPortalLink().

NameTypeRequiredDescription
customerIdstringyesThe Stripe customer (cus_…), from getCheckout(). Allowed: at least 1 character.
returnUrlstringyesWhere the portal's back link goes. Allowed: a URL.

#CustomerPortalLinkOutput

The answer of payments.customerPortalLink().

FieldTypeAlways presentDescription
urlstringyesThe portal page to redirect the customer to.

#OnboardingLinkInput

The input of payments.onboardingLink().

NameTypeRequiredDescription
returnUrlstringyesWhere Stripe sends the owner after onboarding. Allowed: a URL.
refreshUrlstringyesWhere Stripe sends the owner if the link expired or was already used; make a new link there. Allowed: a URL.
type'account_onboarding' | 'account_update'noaccount_onboarding (default) to connect the account, account_update to change its details.
countrystringnoThe two-letter country of the owner's business (ES, US); required the first time the live account is created.

#OnboardingLinkOutput

The answer of payments.onboardingLink().

FieldTypeAlways presentDescription
urlstringyesThe Stripe onboarding page to redirect the owner to (single use).
expiresAtstringyesWhen the link stops working.

#PaymentsStatus

The state of the project's Stripe account, from payments.getStatus().

FieldTypeAlways presentDescription
enabledbooleanyesWhether payments can be used in the current mode.
mode'connect' | 'own_key'yesconnect: payments run on the owner's Stripe account connected through Totalum. own_key: the app uses its own Stripe keys.
accountIdstring | nullyesThe connected Stripe account id (acct_…), or null before the first connection.
livemodebooleanyesWhether this is the live (real money) account; false on the preview and in the sandbox.
chargesEnabledbooleanyesWhether the account can take payments now.
payoutsEnabledbooleanyesWhether Stripe can pay out to the owner's bank account.
detailsSubmittedbooleanyesWhether the owner finished Stripe's onboarding form.
requirements{ currentlyDue, pastDue, eventuallyDue }yesWhat Stripe still needs from the owner.
requirements.currentlyDuestring[]yesInformation Stripe needs now to keep the account working.
requirements.pastDuestring[]yesInformation that is overdue: charges or payouts may be paused until it is given.
requirements.eventuallyDuestring[]yesInformation Stripe will need later.
liveEnabledbooleanyesWhether the owner switched live payments on for the published site.
disconnectedAtstring | nullnoWhen the owner disconnected the Stripe account, or null.

#RefundInput

The input of payments.refunds.create().

NameTypeRequiredDescription
paymentIntentIdstringyesThe payment to refund (pi_…), from getCheckout() or a payment webhook. Allowed: at least 1 character.
amountnumbernoFor a partial refund, the amount in the smallest currency unit. Default: everything not yet refunded. Allowed: > 0.
reason'duplicate' | 'fraudulent' | 'requested_by_customer'noWhy, as Stripe records it: duplicate, fraudulent or requested_by_customer.

#RefundOutput

A refund, from payments.refunds.create().

FieldTypeAlways presentDescription
idstringyesThe refund id (re_…).
statusstringyesStripe's status: succeeded, pending, requires_action, failed or canceled.
amountnumberyesThe refunded amount in the smallest currency unit.
currencystringyesThe currency, lower case.

#Subscription

A Stripe subscription, from payments.subscriptions.*.

FieldTypeAlways presentDescription
idstringyesThe subscription id (sub_…).
status'unpaid' | 'active' | 'paused' | 'incomplete' | 'incomplete_expired' | 'trialing' | 'past_due' | 'canceled'yesGive access while active or trialing. past_due/unpaid: a renewal failed. canceled: ended. incomplete/incomplete_expired: the first payment did not go through. paused: a trial ended without a payment method.
customerIdstringyesThe Stripe customer (cus_…).
cancelAtPeriodEndbooleanyestrue when it ends at currentPeriodEnd instead of renewing.
currentPeriodEndstring | nullyesWhen the paid period ends: the next renewal, or the end of access when cancelAtPeriodEnd.
canceledAtstring | nullyesWhen it was canceled, or null.
metadataRecord<string, string>yesThe metadata given to the Checkout that created it.

#SubscriptionUpdateInput

The change payments.subscriptions.update() makes.

NameTypeRequiredDescription
cancelAtPeriodEndbooleanyestrue: end the subscription when the paid period ends. false: keep renewing (undo a cancellation).