Appearance
Errors and FAQs
Error handling
| Error code and type | Reason |
|---|---|
| 400 Bad Request | Missing or invalid values (for example, a required field is empty). |
| 401 Unauthorized | No valid API key provided. |
| 402 Request Failed | The request was valid but failed (for example, a payment was declined). |
| 403 Forbidden | Your API key does not have permission for this request (common with restricted keys). |
| 404 Not Found | The requested resource does not exist (for example, the ID is wrong). |
| 409 Conflict | The request conflicts with another request (for example, an idempotency key issue). |
| 424 External Dependency Failed | A service Stripe depends on failed, for example the bank or the card network. |
| 429 Too Many Requests | Too many requests in a short time; retry after a short delay. |
| 500, 502, 503, 504 Server Errors | Stripe-side error; retry after a short delay. |
Stripe actions throw on error rather than returning an error object. Wrap an action in a Try/Catch (or handle the workflow error) when a failure is a normal outcome you need to react to, such as a declined card on Confirm Payment Intent.
Good to know
A card decline is a thrown error, not a result
Confirm Payment Intent throws when the card is declined, so the action produces no result. Catch the error, then run Retrieve Payment Intent on the same id and read last_payment_error.code, last_payment_error.decline_code, and last_payment_error.message to learn why.
Amounts are in the smallest currency unit
Every monetary value (amounts, balances) is in the smallest unit of the currency: 1000 is $10.00 in USD. Nothing is auto-converted, so multiply and divide by 100 yourself when displaying or collecting amounts.
Test mode and live mode never mix
The connection's mode follows the key: sk_test_... is test mode, sk_live_... is live. Objects never cross modes, so a cus_... id created with a test key returns “No such customer” under a live key. Use test keys in the Editor and Staging, live keys in Production.
Date filters are in seconds
List filters like created and due_date take Unix timestamps in seconds, not milliseconds. 1704067200 is 1 Jan 2024.
Emptying a field does not clear it
On update actions, empty values ("", [], {}) are stripped before the request, so you cannot blank out a field by sending an empty value, only set a new one. The one exception is metadata: setting a key to "" deletes that key.
expand needs the data. prefix on lists
To expand nested objects, use bare paths on single-object actions (e.g. customer on Retrieve …), and data.-prefixed paths on list and search actions (e.g. data.customer). Left empty, a list returns 10 records; page with Starting After using the last record's id.
A deleted customer still returns
Retrieve Customer on a deleted customer succeeds and returns a minimal object { "id": "cus_…", "deleted": true }. Check deleted before reading other properties.
FAQs
Do I need both keys in WeWeb?
Yes, both are required on the connection. The Publishable Key is the one Stripe’s own interface code uses in the browser (Stripe.js, embedded Checkout), and the Secret Key or Restricted Key is the one Stripe actions use from your WeWeb backend.
Why is my amount 100x larger or smaller than expected?
Most Stripe amounts are in the smallest currency unit (for example cents). For USD, 1000 means $10.00.
Can I use a restricted key?
Yes, but make sure it has permission for the resources you use (for example Payment Intents, Customers, Products, Subscriptions, or Invoices).
See also
- Setup — Connection steps and common pitfalls (wrong keys, amounts in cents, restricted keys, limitations).

