Base URL
1
| https://api.sendpromptly.app/api
|
All public ingest endpoints:
POST /api/v1/receiptPOST /api/v1/result
1
2
3
4
| Authorization: Bearer sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Idempotency-Key: <unique-key-for-this-request>
Content-Type: application/json
Accept: application/json
|
POST /api/v1/receipt
Signal that your app has verified the payment webhook and durably accepted the work. Send this before your job queue runs the business effect.
Stripe request body
1
2
3
4
5
6
7
8
9
| {
"provider": "stripe",
"stripe_event_id": "evt_123",
"event_type": "checkout.session.completed",
"effect_type": "access_unlock",
"internal_reference": "user_456",
"occurred_at": "2026-05-16T15:04:05Z",
"timeout_minutes": 30
}
|
Shopify request body
1
2
3
4
5
6
7
8
9
| {
"provider": "shopify",
"provider_event_id": "wh_orders_paid_abc123",
"event_type": "orders/paid",
"effect_type": "access_unlock",
"internal_reference": "order_98765",
"shopify_shop_domain": "mystore.myshopify.com",
"occurred_at": "2026-05-16T10:00:00Z"
}
|
Fields
| Field | Required | Notes |
|---|
provider | Yes | stripe or shopify. |
stripe_event_id | Stripe only | The Stripe event identifier. Accepted for backward compatibility. |
provider_event_id | Shopify / preferred | Canonical event ID. Preferred for all new integrations. |
event_type | Yes | Stripe: checkout.session.completed, invoice.paid, customer.subscription.deleted, customer.subscription.updated, charge.refunded, charge.dispute.created. Shopify: orders/paid, orders/fulfilled, customers/create, checkouts/create. |
effect_type | Yes | access_unlock, credit_grant, seat_update, subscription_state_apply, access_revocation, credit_deduction. |
internal_reference | Yes | Your internal user, workspace, or account reference. |
occurred_at | Yes | ISO 8601 timestamp. |
shopify_shop_domain | Shopify only | e.g. mystore.myshopify.com. |
timeout_minutes | No | Override the project’s default incident timeout for this event. |
Success response
202 Accepted
1
2
3
4
5
| {
"event_id": "evtrec_123",
"timeout_at": "2026-05-16T15:34:05Z",
"accepted": true
}
|
POST /api/v1/result
Signal the outcome after your business effect succeeds or fails. If no result arrives before the timeout, SendPromptly opens an incident automatically.
Success request
1
2
3
4
| {
"stripe_event_id": "evt_123",
"status": "success"
}
|
Failed request
1
2
3
4
5
6
| {
"stripe_event_id": "evt_123",
"status": "failed",
"error_code": "access_update_failed",
"error_message": "User row lock timeout"
}
|
Reprocess result request
1
2
3
4
5
| {
"stripe_event_id": "evt_123",
"status": "success",
"replay_id": "rp_123"
}
|
Success response
200 OK
1
2
3
4
5
| {
"event_id": "evtrec_123",
"status": "succeeded",
"incident": null
}
|
Common error responses
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| {
"error": {
"code": "validation_error",
"message": "Request validation failed.",
"details": {
"fields": {
"status": [
"The status field is required."
]
}
},
"request_id": "req_123"
}
}
|
Important codes:
missing_idempotency_keyvalidation_errorunauthorizedsubscription_requirednot_foundmissing_accept_headernot_acceptableunsupported_media_typetoo_many_fieldspayload_too_largerate_limitedinternal_error
Repair callback contract
When an operator clicks Reprocess, SendPromptly POSTs a signed request to your project’s repair callback URL.
1
2
3
| X-SendPromptly-Timestamp: <unix_timestamp>
X-SendPromptly-Nonce: <nonce>
X-SendPromptly-Signature: v1=<hmac_sha256>
|
The signature covers:
1
| timestamp + "." + nonce + "." + raw_body
|
Security requirements:
- Reject callbacks with a timestamp older than 5 minutes
- Verify the HMAC-SHA256 signature using your project’s repair signing secret
- Make the repair handler idempotent by
replay_id — the same replay_id may arrive more than once on retries - Reprocess retries on network error or 5xx only; 4xx responses are not retried
Callback body
1
2
3
4
5
6
7
8
| {
"replay_id": "rp_123",
"stripe_event_id": "evt_123",
"event_type": "checkout.session.completed",
"effect_type": "access_unlock",
"internal_reference": "user_456",
"requested_at": "2026-05-16T15:40:00Z"
}
|
After running your repair logic, call POST /api/v1/result with the replay_id to close the loop.