Products
View as MarkdownProducts are reusable catalogue items, each with a fixed price and its own hosted
checkout URL. List them to power the "fixed product → share a URL" flow: create the
product once in the dashboard, then hand its url to a shopper to take a payment. No
per-charge API call required. Storefronts that hold those products are
Storefronts.
GET https://api.worthypayments.com/v1/products
Scope: products:read.
List products#
GET /products
Query parameters#
| Parameter | Type | Default | Notes |
|---|---|---|---|
limit | integer | 10 | Page size. Capped at 100. |
starting_after | string | — | The opaque next_cursor from the previous page. Not a product id. |
Paging is cursor-based, so there is no page parameter and no active filter.
Unrecognized query parameters are silently ignored, so filtering client-side on the
active field is the only option.
Example#
curl "https://api.worthypayments.com/v1/products?limit=10" \
-H "x-api-key: sk_live_xxx"
Response#
{
"object": "list",
"data": [
{
"id": "4b1e77a0-2c93-45de-8f0a-6d5c39ab72e1",
"object": "product",
"name": "Pro Plan",
"active": true,
"url": "https://app.worthypayments.com/checkout/proplan"
}
],
"has_more": false,
"next_cursor": "djJ8MjAyNi0wOC0yNFQxNDo0Njo1Nlp8NGIxZTc3YTA"
}
See Pagination for the cursor list model.
| Field | Type | Notes |
|---|---|---|
id | string | Product id. |
object | string | Always "product". |
name | string | Display name. |
active | boolean | Whether the product is purchasable. |
url | string | null | The product's hosted checkout page. Share this to take a payment. null when the product has no active checkout link. |
Price is not returned. The list carries no
amountorcurrency, so you cannot render a price from this endpoint. Read it from the dashboard or from the hosted checkout page itself.
The fixed-product flow#
- Create a product in the dashboard (name, price, currency).
GET /productsto retrieve itsurl.- Put the URL anywhere a shopper can click it: an email, an invoice, a button, a QR code.
- The hosted page runs fraud, routing, and 3-D Secure, then collects payment. Nothing else to build.
This is the same hosted engine as a checkout link, with the
product carrying a fixed price and a stable URL. To bind a custom checkout link to a
product, pass product_id to POST /checkout-links.
Tax rates#
Your own store (WooCommerce, a custom cart) can use the tax rates you keep with us: create the rates, attach them to products, and ask what each cart line owes at checkout.
POST https://api.worthypayments.com/v1/tax_rates
GET https://api.worthypayments.com/v1/tax_rates
GET https://api.worthypayments.com/v1/tax_rates/{id}
POST https://api.worthypayments.com/v1/tax_rates/{id}
DELETE https://api.worthypayments.com/v1/tax_rates/{id}
POST https://api.worthypayments.com/v1/products/{id}/tax_rates
DELETE https://api.worthypayments.com/v1/products/{id}/tax_rates/{tax_rate}
POST https://api.worthypayments.com/v1/tax/calculate
Scopes: tax:read (list, retrieve, calculate) and tax:write (everything else).
tax:write is server-only. Neither is on a new key by default: tick them in
Dashboard → Developers → API keys.
1. Create a rate#
percentage is a percent: 7.25 means 7.25 %. It comes back as the string "7.25".
Creating requires an Idempotency-Key, so a retry never makes a second rate.
curl https://api.worthypayments.com/v1/tax_rates \
-H "x-api-key: sk_live_xxx" \
-H "Idempotency-Key: 5d0c7a52-3f1e-4c8b-9d2a-6e4f1b7c8a90" \
-H "Content-Type: application/json" \
-d '{"display_name":"CA sales tax","percentage":7.25,"tax_type":"sales_tax","country":"US","state":"CA"}'
Updating (POST /tax_rates/{id}) changes only the fields you send. Deleting stops the rate
applying at once; the record is kept so past tax stays explained. To pause a rate, send
active: false instead. The default rate and global rates are set in the dashboard.
2. Attach it to a product#
curl https://api.worthypayments.com/v1/products/4b1e77a0-2c93-45de-8f0a-6d5c39ab72e1/tax_rates \
-H "x-api-key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"tax_rate":"6f1c2a4e-1d7b-4b8e-9b0a-2f5d3c9e7a11"}'
A product can carry several rates, and they stack. The product id is not checked against
the catalog: use the same id you will send as line_items[].product when you calculate.
3. Calculate at checkout#
curl https://api.worthypayments.com/v1/tax/calculate \
-H "x-api-key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"currency":"usd","address":{"country":"US","state":"CA"},
"line_items":[{"product":"4b1e77a0-2c93-45de-8f0a-6d5c39ab72e1","amount":2000,"quantity":2,"reference":"cart-item-1"}]}'
amount is the line total in cents. The response gives each line its amount_tax and a
tax_breakdown per rate, plus amount_subtotal, tax_amount_exclusive,
tax_amount_inclusive and amount_total. The call writes nothing, so run it every time the
cart changes.
Each line picks its rates on its own, in this order: a global rate, then the rates
attached to its product, then your rates for the ship-to address, then your default rate.
A line with none of these pays no tax. Tax on an inclusive rate is already inside
amount, so only exclusive tax is added to amount_total. Shipping is not taxed by this
call. At most 100 lines per call.
