Appearance
Payment Intents
The Payment Intents API manages the lifecycle of Stripe PaymentIntents for ecommerce checkout.
Payment Intent Flow
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Client │ │ TransactCore│ │ Stripe │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ POST /payment- │ │
│ intents │ │
│──────────────────>│ │
│ │ Create Intent │
│ │──────────────────>│
│ │ client_secret │
│ │<──────────────────│
│ client_secret │ │
│<──────────────────│ │
│ │ │
│ stripe.confirm │ │
│ Payment() │ │
│─────────────────────────────────────>│
│ Payment result │
│<─────────────────────────────────────│
│ │ │
│ GET /payment- │ │
│ intents/{id} │ │
│──────────────────>│ Sync status │
│ │──────────────────>│
│ status: │ │
│ succeeded │ │
│<──────────────────│ │Create Payment Intent
Create a Stripe PaymentIntent for processing a payment.
POST /v1/ecommerce/payment-intentsAuthentication: OAuth Token
Scope: transactcore:payment-intents.create
Rate Limit: 100/min per IP
Request Body
json
{
"organization_id": "org_00000k1L2m3N4o5",
"amount": 3420,
"currency": "usd",
"metadata": {
"order_type": "takeout",
"quote_token_id": "qt_abc123"
}
}Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
organization_id | string | Yes* | Organization hashkey — TransactCore resolves the connected Stripe account for this organization |
connected_account_id | string | Yes* | Connected account hashkey — use this if you already know the specific account |
amount | integer | Yes | Amount in cents (e.g., 3420 = $34.20). Minimum: 50 ($0.50) |
currency | string | No | Three-letter ISO currency code (default: usd) |
metadata | object | No | Arbitrary key-value pairs attached to the Stripe PaymentIntent |
*One of organization_id or connected_account_id is required.
Response
json
{
"client_secret": "pi_3abc123_secret_xyz789",
"payment_intent_id": "pi_3abc123",
"publishable_key": "pk_live_xxxxx",
"amount": 3420,
"currency": "usd"
}Status: 201 Created
Response Fields
| Field | Type | Description |
|---|---|---|
client_secret | string | Stripe client secret — pass this to stripe.confirmPayment() on the frontend |
payment_intent_id | string | Stripe PaymentIntent ID — store this on your backend for order tracking |
publishable_key | string | Stripe publishable key (same as from /config/stripe) |
amount | integer | Confirmed amount in cents |
currency | string | Currency code |
Error Responses
404 — No payment account configured:
json
{
"error": "No payment account configured for this location",
"organization_id": "org_00000k1L2m3N4o5"
}The organization does not have a connected Stripe account. The account must be created and onboarded through the admin dashboard before payments can be accepted.
400 — Account cannot accept payments:
json
{
"error": "Payment account cannot accept payments",
"details": {
"status": "restricted",
"charges_enabled": false,
"requirements": "incomplete"
}
}The connected Stripe account exists but has incomplete onboarding or is restricted.
422 — Validation error:
json
{
"message": "The amount field must be at least 50.",
"errors": {
"amount": ["The amount field must be at least 50."]
}
}Get Payment Intent
Retrieve the current status of a payment intent. TransactCore syncs with Stripe in real-time for non-terminal statuses.
GET /v1/ecommerce/payment-intents/{payment_intent_id}Authentication: OAuth Token
Scope: transactcore:payment-intents.read
Rate Limit: 100/min per IP
Path Parameters
| Parameter | Type | Description |
|---|---|---|
payment_intent_id | string | The Stripe PaymentIntent ID (e.g., pi_3abc123) |
Response
json
{
"data": {
"payment_intent_id": "pi_3abc123",
"amount": 3420,
"currency": "usd",
"status": "succeeded",
"capture_method": "automatic"
}
}Response Fields
| Field | Type | Description |
|---|---|---|
payment_intent_id | string | Stripe PaymentIntent ID |
amount | integer | Amount in cents |
currency | string | Currency code |
status | string | Current status (see table below) |
capture_method | string | Capture method (automatic or manual) |
Payment Intent Statuses
| Status | Description |
|---|---|
requires_payment_method | Awaiting payment method from customer |
requires_confirmation | Payment method collected, awaiting confirmation |
requires_action | Customer authentication required (e.g., 3D Secure) |
requires_capture | Payment authorized, awaiting capture (manual capture only) |
processing | Payment is being processed |
succeeded | Payment completed successfully |
canceled | Payment was canceled |
Real-Time Sync
For non-terminal statuses (requires_*, processing), TransactCore syncs with Stripe before returning the response. This handles the race condition between client-side confirmation and webhook delivery — you can poll this endpoint immediately after stripe.confirmPayment() to get the latest status.
Error Response
404 — Payment intent not found:
json
{
"error": "Payment intent not found"
}Cancel Payment Intent
Cancel a payment intent. Use this when order creation fails after payment confirmation, to release the hold on the customer's card.
POST /v1/ecommerce/payment-intents/{payment_intent_id}/cancelAuthentication: OAuth Token
Scope: transactcore:payment-intents.create
Rate Limit: 100/min per IP
Path Parameters
| Parameter | Type | Description |
|---|---|---|
payment_intent_id | string | The Stripe PaymentIntent ID (e.g., pi_3abc123) |
Response
json
{
"status": "cancelled",
"payment_intent_id": "pi_3abc123"
}Error Responses
404 — Payment intent not found:
json
{
"error": "Payment intent not found"
}422 — Unable to cancel:
json
{
"error": "Unable to cancel payment intent",
"message": "This PaymentIntent has already succeeded and cannot be canceled."
}A payment intent can only be canceled if it has not yet reached the succeeded status. If the payment has already been captured, you will need to create a refund instead.
Best Practices
- Always cancel on failure — If order creation fails after payment confirmation, cancel the payment intent to release the customer's funds.
- Store the payment_intent_id — Save the
payment_intent_idon your backend when creating the intent, before sending theclient_secretto the frontend. This ensures you can always look up or cancel the payment. - Poll for status — After
stripe.confirmPayment(), pollGET /payment-intents/{id}to confirm the final status before creating the order. - Use metadata — Attach order identifiers to the payment intent
metadatafor easier reconciliation. - Handle 3D Secure — Use
redirect: 'if_required'instripe.confirmPayment()to handle SCA/3DS challenges without forcing a redirect.
Changelog
| Date | Change |
|---|---|
| 2026-03-19 | Added connected account lookup endpoint and fixed scope format. |
| 2026-03-19 | Initial publication. |