Shadow Stripe flow
Run the advanced Stripe-specific shadow Checkout flow for CI and launch rehearsal.
API reference
Shadow Stripe flow
Shadow mode is the Stripe-specific automation path for validating a real test-mode Checkout session and proving the expected database side effect occurred. It lives outside API v1 because the workflow is provider-specific and interactive.
Use shadow runs for CI preview verification, launch rehearsal, and debugging webhook-to-database propagation. Requires test-mode Stripe keys and a mapped Supabase verification table.
Endpoints
/api/projects/:projectId/shadow/startCreates a test-mode Checkout session and returns a hosted payment URL.
/api/projects/:projectId/shadow/finalizeVerifies the session reached paid and polls Supabase for the mapped side effect.
Authentication uses the same bearer API keys as API v1 (Authorization: Bearer pf_live_…).
Request and response
Start
POST /api/projects/:projectId/shadow/start
Authorization: Bearer pf_live_...
Content-Type: application/json
Idempotency-Key: ci-preview-123
{
"previewUrl": "https://preview.example.com",
"source": "github_action"
}
| Field | Required | Description |
|---|---|---|
previewUrl | No | Base URL for success/cancel redirects when not set on integration |
source | No | api or github_action — stored on the check run for audit |
Response:
{
"runId": "uuid",
"status": "running",
"traceId": "pf_trace_…",
"checkoutSessionId": "cs_test_…",
"checkoutUrl": "https://checkout.stripe.com/c/pay/…"
}
Finalize
POST /api/projects/:projectId/shadow/finalize
Authorization: Bearer pf_live_...
Content-Type: application/json
{
"runId": "uuid",
"traceId": "pf_trace_…",
"checkoutSessionId": "cs_test_…"
}
Response on success:
{
"runId": "uuid",
"traceId": "pf_trace_…",
"status": "success",
"stage": "supabase_side_effect",
"message": "Shadow checkout verified end to end."
}
Failed responses include stage (stripe_payment or supabase_side_effect) and probe-level details for triage.
When to use it
| Scenario | Why shadow mode |
|---|---|
| CI preview verification | Prove billing path on every PR deploy without manual card entry |
| Launch rehearsal | Walk through pricing flow before opening signups |
| Webhook debugging | Isolate whether failure is Stripe, webhook, or Supabase write |
| Revenue Watch setup | Confirm mapping before enabling production reconciliation |
Required Stripe integration fields
Configure these on the project's Stripe integration before starting a shadow run:
| Field | Purpose |
|---|---|
priceId | Stripe Price used for the synthetic Checkout line item |
verifyTableName | Supabase table where fulfillment rows appear |
verifyTraceColumn | Column containing the trace ID your webhook writes |
PreFlight can scan the connected Supabase OpenAPI schema and suggest the strongest mapping. If the saved mapping misses during a run, verification also attempts discovered trace-bearing tables before failing.
Optional verification fields
| Field | Purpose |
|---|---|
verifyStatusColumn | Column that must match expected status |
verifyExpectedStatus | Expected value (e.g. active, paid) |
verifyCreatedAtColumn | Timestamp column for recency validation |
verifyWindowSeconds | How long finalize polls for async side effects |
previewUrl | Default base URL for redirect URLs |
successUrl / cancelUrl | Override Checkout redirect targets |
Trace ID propagation
PreFlight generates a pf_trace_… ID and embeds it in:
- Checkout session
metadata.preflight_trace_id client_reference_id- Payment intent metadata
Your webhook handler should persist the same trace value to verifyTraceColumn so finalize and Revenue Watch can find the row.
Idempotency
Send an Idempotency-Key header on shadow/start from CI. If the deploy job retries, PreFlight returns the existing shadow run and Checkout URL instead of creating a second session.
Daily start limits apply per project (SHADOW_START_LIMIT_PER_DAY). Use idempotency to avoid exhausting the budget on flaky pipelines.
Rate limits
| Bucket | Limit |
|---|---|
| Auth fingerprint | 40 requests / minute |
| Per project | 4 starts / minute |
Test keys only
Shadow start rejects secret keys that do not start with sk_test_. Live keys cannot be used for synthetic Checkout sessions.
Probe timeline
Each shadow run writes deterministic probe rows:
| Probe key | Stage |
|---|---|
stripe_shadow_checkout_start | Session created |
stripe_shadow_checkout_payment | Payment verified in Stripe |
supabase_shadow_side_effect | Row found in mapped table |
Inspect these in Checks → run timeline or via GET /api/v1/projects/:id/checks/:runId.
Not part of generic API v1
Shadow endpoints remain fully supported but are documented separately from the standardized public API because they are Stripe-specific and workflow-specific. Automation that only needs pass/fail should still read check run status from API v1.
