Commet
  • Pricing
Log InTry out
Introduction

Quickstart

Learn

Accept One-Time Payments

Resources

SDK ReferenceAPI VersioningError HandlingTestingCLI

Plugins

Better Auth
System status
DocumentationKnowledge BaseBuild with AIAPI ReferenceWebhooks

Accept One-Time Payments

Charge customers once with the Commet payments resource — no subscription or plan required. Tax, invoice, and receipt handled automatically.

A payment is a standalone one-time charge with no subscription or plan attached.

Commet calculates tax, generates an invoice, and sends a receipt on every payment automatically.

For lifetime deals and one-off purchases billed as a plan (trials, intro offers, add-ons, consumption models), use One-Time Plans instead.

Link vs. charge

There are two ways to take a one-time payment.

  • Link (payments.create): builds a hosted payment link. The customer opens the url and pays with any card. Vaults the payment method on confirmation.
  • Charge (payments.charge): bills a customer's already-vaulted payment method off-session. No customer interaction, no url.

Create a payment link

Returns a Payment with a url. Redirect the customer to it to collect payment.

const { data } = await commet.payments.create({
  amount: 25000,
  currency: 'usd',
  description: 'Annual report',
  customerId: 'user_123',
  successUrl: 'https://yourapp.com/thanks',
})

redirect(data.url)
response = commet.payments.create(
    amount=25000,
    currency='usd',
    description='Annual report',
    customer_id='user_123',
    success_url='https://yourapp.com/thanks',
)

redirect(response.data['url'])
result, err := client.Payments.Create(ctx, &commet.CreatePaymentParams{
    Amount:      25000,
    Currency:    "usd",
    Description: "Annual report",
    CustomerID:  "user_123",
    SuccessURL:  "https://yourapp.com/thanks",
})

// redirect(result.Data.URL)
CreatePaymentParams params = CreatePaymentParams.builder()
    .amount(25000)
    .currency("usd")
    .description("Annual report")
    .customerId("user_123")
    .successUrl("https://yourapp.com/thanks")
    .build();
ApiResponse<Payment> result = commet.payments().create(params);

// redirect(result.getData().getUrl())
$result = $commet->payments->create(
    amount: 25000,
    currency: 'usd',
    description: 'Annual report',
    customerId: 'user_123',
    successUrl: 'https://yourapp.com/thanks',
);

redirect($result->data['url']);
curl -X POST https://commet.co/api/v1/payments \
  -H "x-api-key: $COMMET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 25000,
    "currency": "usd",
    "description": "Annual report",
    "customerId": "user_123",
    "successUrl": "https://yourapp.com/thanks"
  }'
commet payments create \
  --amount 25000 \
  --currency usd \
  --description "Annual report" \
  --customer-id user_123 \
  --success-url https://yourapp.com/thanks

amount is in cents. 25000 is $250.00.

Parameters

ParameterTypeRequiredDescription
amountnumberYesCharge amount in cents
currencystringYesISO 4217 currency code (usd, eur, brl)
descriptionstringYesShown on the payment link, invoice, and receipt
customerIdstringNoCommet customer ID (cus_xxx) or your external ID
successUrlstringNoWhere the customer lands after paying
metadataobjectNoKey-value pairs. Shape: { [key: string]: string }

Charge a saved payment method

Bills a customer's vaulted payment method off-session. The customer must have a payment method on file.

const { data } = await commet.payments.charge({
  customerId: 'user_123',
  amount: 25000,
  currency: 'usd',
  description: 'Annual report',
})
response = commet.payments.charge(
    customer_id='user_123',
    amount=25000,
    currency='usd',
    description='Annual report',
)
result, err := client.Payments.Charge(ctx, &commet.ChargePaymentParams{
    CustomerID:  "user_123",
    Amount:      25000,
    Currency:    "usd",
    Description: "Annual report",
})
ChargePaymentParams params = ChargePaymentParams.builder()
    .customerId("user_123")
    .amount(25000)
    .currency("usd")
    .description("Annual report")
    .build();
ApiResponse<Payment> result = commet.payments().charge(params);
$result = $commet->payments->charge(
    customerId: 'user_123',
    amount: 25000,
    currency: 'usd',
    description: 'Annual report',
);
curl -X POST https://commet.co/api/v1/payments/charge \
  -H "x-api-key: $COMMET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "user_123",
    "amount": 25000,
    "currency": "usd",
    "description": "Annual report"
  }'
commet payments charge \
  --customer-id user_123 \
  --amount 25000 \
  --currency usd \
  --description "Annual report"

Parameters

ParameterTypeRequiredDescription
customerIdstringYesCommet customer ID (cus_xxx) or your external ID
amountnumberYesCharge amount in cents
currencystringYesISO 4217 currency code (usd, eur, brl)
descriptionstringYesShown on the invoice and receipt
metadataobjectNoKey-value pairs. Shape: { [key: string]: string }

Retrieve a payment

const { data } = await commet.payments.get({ id: 'pay_123' })

List payments

const { data } = await commet.payments.list({
  customerId: 'user_123',
  limit: 20,
})
ParameterTypeRequiredDescription
customerIdstringNoFilter to one customer
limitnumberNoPage size
cursorstringNoPagination cursor from the previous page

Cancel a payment link

Cancels a pending link so it can no longer be paid.

await commet.payments.cancel({ id: 'pay_123' })

Only a link that has not been paid or started processing can be canceled. Charges cannot be canceled.

The Payment object

FieldTypeDescription
idstringPayment ID (pay_xxx)
customerIdstring | nullCustomer the payment belongs to
kind"link" | "charge"How the payment was taken
statusstringCurrent state (see below)
provider"stripe" | "commet" | "dlocal"Payment provider that processed it
amountSubtotalnumberPre-tax amount in cents
taxAmountnumberTax in cents
amountTotalnumberSubtotal + tax in cents
currencystringISO 4217 currency code
descriptionstringDescription set at creation
metadataobject | nullKey-value pairs set at creation
urlstring | nullHosted payment link. null for charges
expiresAtstring | nullWhen the link expires
createdAtstringISO 8601 datetime
updatedAtstringISO 8601 datetime
object"payment"Object type
livemodebooleanfalse for sandbox payments

Statuses

  • pending: The link was created and is waiting for the customer to pay.
  • processing: The payment is being confirmed with the provider.
  • succeeded: The payment completed and an invoice was generated.
  • requires_action: The customer must complete an extra step such as 3D Secure.
  • failed: The payment did not go through.
  • canceled: The link was canceled before payment.

failed and requires_action are not terminal for links: the customer can reopen the same payment link and pay with another card, as long as the link hasn't expired.

View in the dashboard

Navigate to Payments. Each payment shows its status, amount, tax, customer, and the generated invoice.

Limitations

  • amount is in cents — minor units of the currency
  • Tax is calculated automatically and added on top of amount
  • payments.charge requires a vaulted payment method on the customer
  • Charges cannot be canceled
  • A link can only be canceled while pending

Related

  • One-Time Plans — One-time charges billed as a plan
  • Invoices and Billing Cycles — How invoices are generated
  • Manage Customers — Create customers and vault payment methods
  • SDK Reference — Node.js SDK methods
  • CLI — Create payment links from the terminal

How is this guide?

Handle Failed Payments

What happens when a customer's payment fails and how they can reactivate from the Customer Portal.

Finance Overview

How money flows through Commet — balances, payouts, and transaction history.

On this page

Link vs. charge
Create a payment link
Parameters
Charge a saved payment method
Parameters
Retrieve a payment
List payments
Cancel a payment link
The Payment object
Statuses
View in the dashboard
Limitations
Related