Skip to content
How it worksProductPricingDocs
Sign inGet started

Docs

  • Quickstart
  • Stripe SDK drop-in
  • JSON API
  • Idempotency, modes, errors
  • Signed callbacks
  • Payment methods and routing

Docs

Stripe SDK drop-in

Keep your Stripe Checkout code. Point the SDK at Cortana, use a Cortana key, and payers are routed across your own connected accounts.

Point the SDK at Cortana

Use your ck_test_ or ck_live_ key where the Stripe secret key went, and change the API host. Everything else in the call stays as it is.

import Stripe from "stripe";

const stripe = new Stripe(process.env.CORTANA_KEY, {   // ck_test_… or ck_live_…
  host: "cortanapay.com",
  port: 443,
  protocol: "https",
});

const session = await stripe.checkout.sessions.create({
  mode: "payment",
  line_items: [{
    price_data: { currency: "usd", unit_amount: 2500, product_data: { name: "Pro plan" } },
    quantity: 1,
  }],
  success_url: "https://example.com/thanks?cs={CHECKOUT_SESSION_ID}",
  cancel_url: "https://example.com/cart",
  client_reference_id: "order_1042",
  customer_email: "[email protected]",
  metadata: { order_id: "1042" },
});

res.redirect(303, session.url);

With curl, Basic auth works the same as with Stripe: the key is the username and the password is empty.

Supported

Create, retrieve and expire Checkout Sessions: POST /v1/checkout/sessions, GET /v1/checkout/sessions/:id and POST /v1/checkout/sessions/:id/expire. Form bodies (bracket notation) and JSON are both accepted.

ParameterNotes
mode
Only payment.
line_items[][price_data]
currency, unit_amount (integer minor units) and product_data[name]. All lines share one currency.
line_items[][quantity]
Defaults to 1.
success_url, cancel_url
Public https URLs. {CHECKOUT_SESSION_ID} is replaced with the session id.
client_reference_id
Becomes the invoice external id; it must be unique per workspace.
customer_email
Shown on the receipt; forwarded to your provider only if you allow it.
metadata
Up to 20 string keys. Kept on the invoice and returned in callbacks.
expires_at
Unix time. Between 5 minutes and 30 days from now; default 24 hours.
payment_intent_data[description]
Becomes the invoice description.
template
Cortana extra: split, compact or classic payment page.
allowed_categories[]
Cortana extra: card, crypto and/or bank. Omit to offer every connected method.

Differences from Stripe

BehaviourIn Cortana
Session id
Looks like cs_inv_…. It is the invoice id behind cs_, so the JSON API reads it too.
price ids
Not supported. Send price_data inline.
Other modes
subscription and setup are refused with a clear error.
Ignored params
Anything else Stripe accepts (payment_method_types, locale, …) is ignored, not rejected. Methods come from your connections.
payment_intent
Always null. The payment may run on Stripe, Whop, PayerURL or a bank transfer.
Stripe-Account header
Refused. A key is always one workspace.
Idempotency-Key
Optional. Stripe SDKs always send one. Without it, every request creates a new session, as with Stripe.
Errors
Stripe's shape: { error: { type, code, message, param } }, with the statuses the SDKs map to their exception classes.
Extras
invoice_id, template and paid_at appear on the object; SDKs ignore them.

Learn about payment from a server, not the redirect

Stripe webhooks are not forwarded. Use a Cortana-Signature callback (invoice.paid) or retrieve the session and check payment_status.

Many gateways, one place you control. Payments settle into your own accounts. Cortana never holds your funds.

Product

  • How it works
  • Features
  • Pricing
  • FAQ

Developers

  • Quickstart
  • Stripe SDK drop-in
  • JSON API
  • Signed callbacks

Account

  • Sign in
  • Create account

© 2026 Cortana