Webhooks
Start a workflow from an HTTP call, send HTTP requests from workflow steps, and receive Stripe and Apple payment webhooks in your Anythink project.
Last updated
Anythink handles webhooks in three directions. Another system can call a workflow in your project, a workflow can call another system, and Stripe and Apple can tell Anythink when a payment or subscription changes. This page covers each one, with the exact URL, the authentication and the data your workflow receives.
| Direction | What you use | Authentication |
|---|---|---|
| Your system or a third party calls your project | An API route trigger on a workflow | An API key or user token |
| A workflow calls another system | The Call An API step | Whatever the other system needs, sent in headers |
| Stripe or Apple calls Anythink | The AnythinkPay payments service | Verified by Anythink, nothing for you to configure per request |
The first two are building blocks you wire up yourself. The third is built in: you register one URL with Apple, connect Stripe, and react to the results with an event trigger.
Note: An API route trigger authenticates with a key in a request header, not with a payload signature. The sender has to be able to set an x-api-key or Authorization header.
Start a workflow with an HTTP call#
An API route trigger gives a workflow its own endpoint:
POST https://api.my.anythink.cloud/org/{project_id}/workflows/api/{route}
x-api-key: <your key>
Content-Type: application/json
{ "order_id": "ord_1001", "total": 42.5 }
| Rule | Detail |
|---|---|
| Method | POST only. |
| Route | One path segment, such as order-received, with no slashes. Stored in lower case and matched without regard to case. |
| Uniqueness | Each route is unique across the project's API route triggers, including disabled ones. |
| Authentication | An API key sent as x-api-key, or a user token sent as Authorization: Bearer …. The caller needs the anythink_workflows:trigger permission. |
| Payload | The JSON body becomes the trigger data. Optional id and entity_name query parameters become the trigger id and entity name. |
| Response | 204 No Content once the job is queued. 401 without credentials, 403 without the permission, 404 when no enabled trigger has that route. |
The response doesn't wait for the workflow to run, so this suits work that can finish in the background: imports, syncs and notifications. If the caller needs a result, have the workflow write it to a record the caller reads afterwards.
Create the key#
Give the sender its own API key with only the permission it needs. See API keys for expiry, rotation and revoking.
In the Anythink dashboard
- Open My Account and select the API Keys tab.
- Enter a Name such as
order-webhookand choose Expires in (days). - Under Anythink Permissions, select
anythink_workflows:trigger. - Select Create API Key and copy the key into the sender's secret store. It's shown once.
With the CLI
anythink api-keys create order-webhook \
--permissions anythink_workflows:trigger \
--expires-in 90 \
--yes
The key is written once to standard error. Copy it into the sender's secret store.
With an AI assistant (MCP)
Create an API key called order-webhook with the anythink_workflows:trigger permission, expiring in 90 days, and save it as a profile.
The assistant runs api-keys create through the cli tool. Ask for --save-as so the key goes into a profile and doesn't pass through the conversation.
Create the workflow#
In the Anythink dashboard
- Open Workflows and select New Workflow.
- Enter a Name, for example
order-received. - Under Triggers, set Trigger Type to API Call and enter an API Route such as
order-received, without a leading slash. - Select Create Workflow.
- In the editor, select Add Step and build what should happen. Step types lists the options.
- Select Enable Workflow in the toolbar.
With the CLI
anythink workflows create order-received \
--trigger Api \
--api-route order-received \
--enabled
The command prints the new workflow's id. Add steps with anythink workflows step-add <id> <key> --action <Action> --params '<json>'.
With an AI assistant (MCP)
Create a workflow called order-received with an API trigger on the route order-received, and enable it.
The assistant runs workflows create through the cli tool, then workflows step-add for each step you describe.
Read the payload in a step#
The JSON body is available to every step as $anythink.trigger.data. Use dots for nested objects and square brackets for list items:
{{ $anythink.trigger.data.order_id }}
{{ $anythink.trigger.data.customer.email }}
{{ $anythink.trigger.data.items[0].sku }}
A step's own output is available to later steps as {{ $anythink.steps.<step_key>.data }}. See Template syntax for the full set of expressions.
Check it worked#
Call the route, then look at the job.
curl -X POST "https://api.my.anythink.cloud/org/$ORG_ID/workflows/api/order-received" \
-H "x-api-key: $ANYTHINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"order_id":"ord_1001","total":42.5,"customer":{"email":"ada@example.com"}}'
Expect 204. Then open the workflow in the Anythink dashboard and select View Job History, or run:
anythink workflows jobs <workflow_id>
Each job shows its status and, in the dashboard, the payload it received and the log and output of every step.
To switch the route off, clear Enabled on its API Call trigger in Workflow Settings. Callers then get 404.
Send an HTTP request from a workflow#
The Call An API step sends one HTTP request to any URL your project's workflow runner can reach, and keeps the response for later steps.
| Parameter | Required | Notes |
|---|---|---|
url |
Yes | Templated. Values aren't URL-encoded, so encode them yourself. |
method |
Yes | GET, POST, PUT or DELETE, in capitals. |
headers |
No | An object of header names to values. Values are templated. |
body |
No | Templated. Sent as application/json. |
results_path |
No | A dot path into the JSON response to keep, such as data.items. Without it the whole response is kept. |
On success the step's output is data, the parsed JSON response or the part at results_path. A later step reads it as {{ $anythink.steps.<step_key>.data }}. A non-2xx status fails the step and the job, and the failure records the status_code and the response.
Anythink doesn't sign outgoing requests and doesn't retry a failed call. To let the receiver authenticate your project, keep a shared secret in your project's secrets and send it in a header with {{ $anythink.secrets.<key> }}. See Secrets. To react to a failure, link the step's failure path to another step, such as an email or a Slack message.
Note: Put credentials in headers, not in the URL. Request URLs are written to the step log.
Add the step#
This example posts each order to a partner system, using trigger data and a secret.
{
"url": "https://partner.example.com/v1/orders",
"method": "POST",
"headers": {
"Authorization": "Bearer {{ $anythink.secrets.PARTNER_API_KEY }}",
"X-Source": "anythink"
},
"body": "{\"order_id\": \"{{ $anythink.trigger.data.order_id }}\", \"total\": {{ $anythink.trigger.data.total }}}",
"results_path": "order"
}
In the Anythink dashboard
- Create the secret first: open Settings, select Secrets under Platform Settings, add
PARTNER_API_KEYand save. - Open the workflow and select Add Step, then choose Call An API.
- Give the step a Name and Key, for example
send_to_partner, and tick Enable Step. - Enter the URL and choose the Method.
- Under Headers, select + Add Header for each header.
- Enter the Body and, if you only need part of the response, the Results Path.
- Save the step, then save the workflow.
With the CLI
anythink secrets create PARTNER_API_KEY --value "<the partner's key>"
anythink workflows step-add 42 send_to_partner \
--name "Send to partner" \
--action CallAnApi \
--start --enabled \
--params '{"url":"https://partner.example.com/v1/orders","method":"POST","headers":{"Authorization":"Bearer {{ $anythink.secrets.PARTNER_API_KEY }}"},"body":"{\"order_id\": \"{{ $anythink.trigger.data.order_id }}\"}","results_path":"order"}'
Replace 42 with your workflow's id. To change a step later, use anythink workflows step-update <workflow_id> <step_id> --params '<json>'.
With an AI assistant (MCP)
In workflow 42, add a Call An API step called send_to_partner that POSTs to https://partner.example.com/v1/orders with the header X-Source: anythink, and make it the start step.
The assistant runs workflows step-add through the cli tool.
Receive payment webhooks#
AnythinkPay receives webhooks from Stripe and Apple on a payments service that Anythink runs, not on a route you create. Anythink verifies each event and records it before anything reaches your workflows.
Stripe#
There is nothing to register in Stripe. You connect your Stripe account to your project, and Anythink receives and verifies Stripe's events for it. The events Anythink acts on include:
| Stripe event | What Anythink does |
|---|---|
payment_intent.succeeded, payment_intent.payment_failed |
Updates the payment for mobile payments |
checkout.session.completed, checkout.session.expired |
Updates the payment for web payments |
customer.subscription.created, .updated, .deleted |
Updates the subscription |
invoice_payment.paid |
Records the invoice payment |
payment_method.attached, payment_method.detached, setup_intent.setup_failed |
Updates saved payment methods |
account.updated |
Updates your Stripe Connect account status |
An event type outside this list is acknowledged and ignored. To connect Stripe, see Take payments with Stripe.
Apple#
Apple sends App Store Server Notifications to a URL that you register once in App Store Connect. Anythink gives you the URL.
In the Anythink dashboard
- Open Settings, and under Payments select Apple In-App Purchase. This opens the Apple tab of Settings › Payments.
- Fill in the App Store Connect details and select Save Apple settings. See Verify Apple in-app purchases for where each value comes from.
- Copy the URL shown under App Store Server Notifications.
- In App Store Connect, open your app, then App Information › App Store Server Notifications, and paste the URL for both Production and Sandbox.
- Back in the Anythink dashboard, use the Test ASSN delivery card to send a test notification for each environment.
With the CLI
anythink fetch /integrations/anythinkpay/apple-iap/credentials
anythink fetch "/integrations/anythinkpay/apple-iap/test-notification?environment=sandbox" --method POST
The first command returns the notification_url to register. The second asks Apple to send a test notification to it. Use environment=production for the live environment. Both need a project administrator.
With an AI assistant (MCP)
Show me the App Store Server Notifications URL for this project, then send a sandbox test notification.
The assistant runs the same two fetch commands through the cli tool.
Apple's notifications update subscription status and history in AnythinkPay. They don't start workflow triggers.
React to Stripe payments in a workflow#
When Anythink records a Stripe payment, subscription or saved payment method change, it also raises a matching event in your project. Start a workflow from it with an Event trigger.
| Event | Fires when | Trigger data |
|---|---|---|
PaymentCreated, PaymentSucceeded, PaymentFailed |
A payment is created, succeeds or fails | The payment |
SubscriptionCreated, SubscriptionActivated, SubscriptionExpired |
A subscription is created, activated or expires | The subscription |
PaymentMethodCaptured, PaymentMethodCaptureFailed, PaymentMethodRemoved |
A saved payment method is captured, fails to capture or is removed | The payment method |
The trigger data uses snake_case field names. For a payment that includes id, type, provider, amount, currency, status, description, reference, paid_at and metadata. $anythink.trigger.id is 0 for these events, so identify the record from the trigger data.
In the Anythink dashboard
- Open Workflows and select New Workflow.
- Set Trigger Type to Event and Event Type to Payment Succeeded.
- Select Create Workflow, add your steps, and select Enable Workflow.
- Use
{{ $anythink.trigger.data.amount }}and{{ $anythink.trigger.data.reference }}in step parameters.
With the CLI
anythink workflows create payment-succeeded \
--trigger Event \
--event PaymentSucceeded \
--enabled
Then add steps with anythink workflows step-add.
With an AI assistant (MCP)
Create a workflow called payment-succeeded that runs on the PaymentSucceeded event, and enable it.