Skip to content

Charge your customers with Stripe

Create Stripe customers, checkout sessions, or payment intents from your application. Stripe’s API is form-encoded (not JSON) and authenticates with a secret key, so the service must declare both. Because you want the returned id stored on the record, drive it from a function.

Set the Content-Type to application/x-www-form-urlencoded — the platform then form-encodes the request body, which Stripe requires. The secret key (sk_test_... in test mode) goes in auth_config as a bearer token:

{
"name": "Stripe",
"service_type": "rest",
"base_url": "https://api.stripe.com",
"auth_type": "bearer",
"auth_config": {"token": "sk_test_..."},
"headers": {"Content-Type": "application/x-www-form-urlencoded"}
}

Allow-list api.stripe.com (see the outbound-service-call recipe). Use a test-mode key while building; live keys create real charges.

2. Create a customer (or charge) and store the id

Section titled “2. Create a customer (or charge) and store the id”

A function calls Stripe and returns the id to persist. The flat body is form-encoded on the wire; nested Stripe params use bracket keys ("items[0][price]"):

export function handler(input: any): any {
const r = input.record || {};
const resp: any = Host.invokeService(input.input.service_config_id, {
email: r.email,
name: (r.first_name || "") + " " + (r.last_name || ""),
description: "SaaS customer"
});
const body: any = resp.body || {};
return { stripe_customer_id: body.id || null };
}

The function-backed service’s base_url is the full endpoint (https://api.stripe.com/v1/customers), since Host.invokeService sends no path. Run it with a run_function action (see the LLM recipe); stripe_customer_id is merged onto the record. For a checkout session, post to /v1/checkout/sessions and store the returned id and url.

3. Confirm asynchronously with an inbound webhook

Section titled “3. Confirm asynchronously with an inbound webhook”

A charge’s outcome arrives later as a Stripe webhook, not in the create response. Point Stripe’s webhook at an inbound service on your application and let a rule update the record’s payment status when the checkout.session.completed (or payment_intent.succeeded) event lands. Verify the Stripe signature before trusting the payload.