REST API Reference
An overview of the API that your server calls, and notes on using it. You get the endpoint URL from your STBLpay contact when you onboard (contact). Don't assume a public URL or a localhost default.
The type, format, and constraints of each field, the list of errors, and request and response examples are in the OpenAPI 3.1 specification (view in the browser, openapi.yaml). Use openapi.yaml for code generation or to give to an AI coding agent.
Endpoint list
| Method | Path | Authentication | Purpose |
|---|---|---|---|
POST | /payment_intents | API key (x-stbl-api-key) | Create a payment |
GET | /payment_status/:paymentIntentId | None | Retrieve payment status |
Request and response bodies are JSON, and the fields are camelCase.
Create payment
POST /payment_intents creates a payment and returns the checkoutUrl that you send the buyer to. The fields, errors, and examples are in "Create a payment" in the OpenAPI specification.
- Amounts (such as
amountJpy) are decimal strings, not JSON numbers (example:"4980"). Handle fractions such as fees without converting them to floating-point numbers.amountJpymust be greater than 0 ("0"or a negative value returns 400common/invalid_request). Beyond that, the API imposes no upper or lower limit on the amount. For operational limits, check with your contact. orderIdis an ID for each payment attempt and the idempotency key. Calling again from the same store with the same value returns the existing payment. Use the same value when you resend the request, and a new value when the buyer pays again afterfailed,expired, orcanceled. With multiple stores, assign values that are unique across the whole merchant (constraint across stores).- The hostname of
returnUrlmust exactly match a domain registered in the merchant console (Domain registration). When a payment reaches a terminal state, the checkout page shows a link back: "Back to the shop" (ショップに戻る) if the payment succeeded, or "Back to the payee" (お支払い先に戻る) in any other terminal state. When the buyer clicks it,returnUrlopens with astbl_pay_intentquery parameter (the payment ID) appended. IfreturnUrlalready has a query parameter with the same name, it is overwritten. merchantExpiresAtis the upper limit of the deposit deadline (How deadlines work).- Even if the response
statusiscreated, the payment has not succeeded. Confirm success with a Webhook or a status lookup. feeJpyandnetAmountJpyin the response are estimates. Record the deposit usingnet_received_jpyinpayment.settled(How amounts are handled).
Retrieve payment status
GET /payment_status/:paymentIntentId returns the current status of a payment. The fields, errors, and examples are in "Retrieve payment status" in the OpenAPI specification.
- There is no authentication. No API key or Authorization header is needed.
- A payment ID is not a secret. Do not use it in place of permission to view your own orders.
- This response does not include amounts, fees, or wallets.
Status values
Only settled means the payment succeeded. Base delivery of goods and recording of revenue on this status. The categories, meanings, and transitions of the values are in the status list. The list of values is also under status in the OpenAPI specification.
If you receive an unknown value, do not deliver goods or charge again; treat it as under review.
failed_reason classification codes
failedReason (status lookup) and the Webhook failed_reason contain a failure classification code. The list of codes and their meanings is under failedReason in the OpenAPI specification.
Codes may be added in the future, but the meaning of an existing code does not change. Receivers should not validate the value strictly as an enumeration; fall back to treating an unknown value as a failure. The following codes are handled differently from the rest.
nonce_conflict: The outcome has not been determined. Do not close the order as failed; hold it and refer it for investigation. No Webhook is delivered; it is visible only through a status lookup.userop_expired: The payment isfailed, but the money has arrived. This is a different event fromexpired(no deposit within the deadline). The buyer's JPYC balance has not decreased and can be used for the next payment.merchant_wallet_outdated: You must run "Update" (アップデート) for the receiving wallet in the merchant console.merchant_suspended: A payment moved to a terminal state because of a merchant suspension (Merchant suspension).
For every code except nonce_conflict, the payment ends as failed and has not succeeded.
Errors
The error body is { code, details? }. The error codes and what to do for each endpoint are in the responses of each endpoint in the OpenAPI specification.
{ "code": "common/invalid_request" }
- Branch on
code, and use the HTTP status only as a supplement. Fall back to your common error handling for unknown codes. Codes may be added. - The server does not return display text, so you decide the text to display.
- When a 429 is returned, retry after a pause, regardless of the body's shape. When the network layer in front applies rate limiting, the body does not contain a
code. - Retrying
common/internal(500) with the sameorderIddoes not create the payment twice. However, anorderIdused at a different store also returns this error, and retrying does not resolve that case (constraint across stores).
Refunds are a merchant console feature, and there is no refund API that the merchant server can call (scope of refunds).