API Trigger: Stripe Webhook for email composition
API triggers are the most flexible: Any system that can send a POST request to a URL can trigger your routine.
When should you choose an API trigger?
Scheduled routines run according to the clock. GitHub-event routines react to code changes. Everything else is in the trigger API.
API triggers are the most flexible: Any system that can send a POST request to a URL can trigger your routine. That includes:
- Stripe webhook - customer just paid, upgraded their subscription, and is requesting a refund.
- Sentry Warning - New Error, Threshold Exceeded
- Monitoring systems - Datadog, PagerDuty, Honeycomb - are activated based on a single indicator.
- Customer support tools - new tickets, SLA violations, escalation
- Your own backend system - any events you've announced.
In this lesson, we'll build an example from Anthropic's launch blog post: A Stripe webhook triggers a routine, reads new customer details, and composes a personalized welcome email that's saved to your Gmail drafts folder—ready for the user to review and send.
The structure of the trigger API
When you create a routine that's triggered by the API, Anthropic generates a unique endpoint URL. It looks like this:
https://api.claude.com/v1/routines/{routine-id}/fire
This is the URL your source system sends the POST request to. Authentication takes place via headers—usually the API key generated when you set up your routine. For example:
Authorization: Bearer ccr_xxxxxxxxxxxxxxxxxxx
The request body should be JSON only. Anything you send will be passed to the routine prompt as input data. This is the minimum curl statement required:
curl -X POST "https://api.claude.com/v1/routines/{routine-id}/fire" -H "Authorization: Bearer $CCR_API_KEY" -H "Content-Type: application/json" -d '{ "event": "customer.subscription.created", "customer_id": "cus_abc123", "customer_email": "new@example.com", "plan": "pro_monthly" }'
The routine will be executed. Your prompt can reference any field from that JSON body.
Step 1: Prompt
Start with the prompt, as the prompt identifies the data you need from Stripe. This is the prompt we will use:
Bạn đang viết một email chào mừng được cá nhân hóa cho một khách hàng mới vừa đăng ký. Bạn sẽ nhận được sự kiện `subscription.created` của Stripe làm dữ liệu đầu vào, bao gồm: email khách hàng, tên khách hàng và gói dịch vụ họ đã chọn. Sử dụng Gmail MCP connector để tạo bản NHÁP (không gửi) trong thư mục nháp của Gmail với cấu trúc sau: To: {email khách hàng} From: tôi Subject: Chào mừng bạn đến với {tên sản phẩm} - hãy cùng thiết lập nhé Nội dung (dưới 150 từ): - Lời chào thân thiện ngắn gọn gửi đến khách hàng bằng tên - Đề cập cụ thể đến gói dịch vụ họ đã chọn và những lợi ích mà gói dịch vụ mang lại - Ba hành động cụ thể họ có thể thực hiện ngay hôm nay, được liệt kê bằng dấu chấm đầu dòng - Lời kết "hãy trả lời email này nếu bạn cần bất cứ điều gì" từ tôi Quy tắc: - Luôn tạo dưới dạng bản nháp, không bao giờ gửi - Không bao giờ đề cập đến giá cả, hoàn tiền hoặc nâng cấp - Không bao giờ sử dụng biểu tượng cảm xúc - Nếu thiếu tên khách hàng, hãy sử dụng "there" làm lời chào - Nếu sự kiện không phải là subscription.created, thì không làm gì cả và thoát
Note the defensive patterns:
- The DRAFT-ON instructions are clear - reiterated for safety reasons, although we will also be limiting the token scope.
- Handle empty state - if the event is not as expected, exit.
- Strict word limit - 150 words
- The correct email format and structure.
Step 2: Set up Gmail MCP connector (Minimum scope)
This is where security becomes crucial.
Go to Settings → Connectors → Gmail and start the OAuth routine. When Gmail asks which areas you want to grant permission to, select carefully:
| Scope | Is permission granted? | Reason |
|---|---|---|
gmail.drafts.create |
✅ Yes | Essential - this routine generates drafts |
gmail.send |
❌ NO | We absolutely do not want Claude to send |
gmail.readonly |
❌ NO | This routine does not need to read existing emails. |
gmail.modify |
❌ NO | Don't let routine edit or delete. |
gmail.labels |
❌ NO | Not required for the draft. |
If the connector's user interface doesn't allow you to select individual scopes, use a Google Workspace admin policy or an OAuth application with limited scope. The rule is: if the task is "compose emails," the connector should only be able to compose emails. Not send. Not read. Not edit.
This is the second most common security error in routines (after unfiltered connectors): Granting too much scope to a connector at the time of OAuth.
Step 3: Configure the trigger API
Return to Routines UI:
- Similar routine
- Trigger type : API
- Routine name:
stripe-onboarding-draft - Generate an API key - this is the Bearer token that the Stripe webhook handler will use. Copy it and store it in your secret manager. You will no longer be able to see it.
- Connectors : Gmail only (deselect everything else - see Lesson 2)
- Paste the prompt from step 1
- Save
After saving, you will see the routine's trigger URL. Copy that URL—it will be added to the Stripe webhook configuration.
Step 4: Connect to Stripe
Now connect to Stripe. This is a one-time setup in your Stripe control panel:
- Developers → Webhooks → Add endpoint
- Endpoint URL : Activation URL from the routine
- Events to listen for:
customer.subscription.created(and only this event) - Save
Here's something to note: Stripe sends POST requests directly to your URL with Stripe's event signature in the header, but your routine won't know how to verify that signature itself. You have two options:
Option A : Place a proxy server in between (recommended for production environments). Your server receives the Stripe webhook, verifies the Stripe signature, and then forwards the payload to the routine's trigger URL with your Bearer token. Your server is the trusted boundary.
Option B : Accept that anyone who finds your trigger URL can activate the routine. This is only acceptable for demos, internal testing, or non-sensitive work. If someone guesses or steals the URL + Bearer token, they can activate the routine and consume your limit.
For this lesson, option B would be fine – we're building an email sending routine just for drafting. For a production environment (especially if the routine can send actual messages or modify actual data), always use option A.
This is the minimum Node proxy you can place in front of it:
// Cloudflare Worker, hàm Vercel hoặc bất kỳ endpoint serverless nào export async function POST(request) { // 1. Xác minh signature Stripe const sig = request.headers.get('stripe-signature'); const payload = await request.text(); const event = stripe.webhooks.constructEvent(payload, sig, STRIPE_SECRET); // 2. Lọc theo sự kiện chúng ta quan tâm if (event.type !== 'customer.subscription.created') { return new Response('ignored', { status: 200 }); } / // 3. Chuyển tiếp đến hàm await fetch(process.env.CCR_TRIGGER_URL, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.CCR_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ event: event.type, customer_id: event.data.object.customer, customer_email: event.data.object.customer_email, customer_name: event.data.object.customer_name, plan: event.data.object.items.data[0].price.nickname, }), }); return new Response('ok', { status: 200 }); }
This is approximately 40 connection lines, and it's a safe pattern for any API-triggered routine in a production environment.
Step 5: Test with a fake payload
Before waiting for an actual registration, run the routine manually:
curl -X POST "$CCR_TRIGGER_URL" -H "Authorization: Bearer $CCR_API_KEY" -H "Content-Type: application/json" -d '{ "event": "customer.subscription.created", "customer_id": "cus_test_123", "customer_email": "test@example.com", "customer_name": "Alex Chen", "plan": "Pro Monthly" }'
Open the routine's run history. You will see:
- The request has been received.
- I used the Gmail MCP connector.
- The draft has been created.
- The process is complete.
Open your Gmail drafts folder. There will be a draft addressed to test@example.com, greeting Alex by name, mentioning the Pro Monthly plan, with the next three actions and your signature.
If everything looks good, flip the switch on Stripe. Your next real subscriber will receive a personalized draft in your inbox in just seconds.
Common mistake: Using the same template for "Send actual message"
The question is: "Why didn't I let Claude send the email?"
Don't do that. Not in your initial routines, and not without thorough testing.
Reason:
- Drafts may be reviewed. Actual emails will not.
- Drafts create a natural barrier for users. You see the message before the customer sees it.
- Drafts vary in scale. One wrong draft could send an email to 1,000 customers. A wrong draft only causes embarrassment in the worst-case scenario.
If you need to automate sending later, justify it. Start with drafts, monitor your routine to ensure output quality for 30 days, then consider granting scoped sending permissions. Even then—keep the draft priority option for the most sensitive messages.
Key points to remember
- Trigger APIs unlock any event source, not just GitHub.
- Event data becomes input that your prompt can reference.
- Always set up a proxy server in advance to verify the source signature for the production environment.
- Grant minimum scope OAuth permissions to connectors - drafts.create, not full send.
- Start all new automation routines in draft-only mode, then upgrade to send only after reliability has been proven.
-
Question 1:
What is the MINIMUM permission range you should grant to the routine token for the Gmail MCP connector?
EXPLAIN:
The principle of least privilege prevails. If the task is 'drafting emails for others to review,' the routine only needs the drafts.create permission—no send, no read, no admin. A violated routine can only do what its scope allows.
-
Question 2:
When Stripe triggers a webhook at your routine endpoint, where is the event payload sent?
EXPLAIN:
The payload data becomes input to the routine—you reference it in your prompt just like any other variable. Here's the whole point: The MAIN event data is the work Claude needs to perform.
-
Question 3:
What should you do before connecting any third-party services to a routine's trigger API?
EXPLAIN:
API-triggered routines are publicly accessible endpoints. Without signature verification, anyone who discovers the URL can trigger the routine and consume your limits (or worse, steal connector data). Always verify webhook signatures in your source system or at your proxy server.
Training results
You have completed 0 questions.
-- / --
- How to fix black screen or black stripe in Nox App Player
- How to play the Taurus team composition in TFT Season 14
- 9 basic rules of composition in photography
- The brothers turned 7 lines of code into a $ 35 billion business empire
- 6 free music and lyric composition tools with the help of AI
- The difference of the AMOLED PenTile and Real-Stripe technologies