{"openapi":"3.0.0","paths":{"/health":{"get":{"operationId":"HealthController_check","summary":"Liveness probe","description":"Returns 200 with { status: \"ok\", revision: \"<short commit sha>\" }.","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponseDto"}}}}},"tags":["Health"]}},"/v1/auth/login-payload":{"get":{"operationId":"AuthController_loginPayload","summary":"Get SIWE login payload","description":"Returns a thirdweb SIWE payload for the given wallet address to sign.","parameters":[{"name":"address","required":true,"in":"query","description":"Wallet address (0x...)","schema":{"type":"string"}},{"name":"chainId","required":false,"in":"query","description":"Optional EVM chain id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginPayloadResponseDto"}}}},"400":{"description":"Missing/invalid address or chainId"}},"tags":["Auth"]}},"/v1/auth/verify":{"post":{"operationId":"AuthController_verify","summary":"Verify SIWE signature and issue JWT","description":"Verifies the signed payload, upserts the merchant, and returns a dashboard JWT.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResponseDto"}}}},"400":{"description":"payload and signature are required"},"401":{"description":"Login verification failed"}},"tags":["Auth"]}},"/v1/merchants/me":{"get":{"operationId":"MerchantController_getProfile","summary":"Get merchant profile","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantProfileDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Merchant"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]},"patch":{"operationId":"MerchantController_updateProfile","summary":"Update merchant profile","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMerchantProfileRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantProfileDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Merchant"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/smart-accounts":{"post":{"operationId":"MerchantController_registerSmartAccount","summary":"Register a smart-account address for this merchant","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterSmartAccountRequestDto"}}}},"responses":{"204":{"description":"Registered (idempotent)"},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"409":{"description":"Smart account already claimed by another merchant"}},"tags":["Merchant"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/api-keys":{"get":{"operationId":"MerchantController_listApiKeys","summary":"List API keys","parameters":[{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":false,"in":"header","description":"JWT: required when mode isolation is enabled. API key: inherited from the key; a conflicting header is rejected. Optional during preparation.","schema":{"enum":["live","test"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListApiKeysResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Merchant"],"security":[{"merchant-jwt":[]}]},"post":{"operationId":"MerchantController_createApiKey","summary":"Create an API key","description":"Returns the raw secret key once — store it securely.","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT: required when mode isolation is enabled. API key: inherited from the key; a conflicting header is rejected. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Merchant"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/api-keys/{id}":{"delete":{"operationId":"MerchantController_revokeApiKey","summary":"Revoke an API key","parameters":[{"name":"id","required":true,"in":"path","description":"API key id","schema":{"type":"string"}},{"name":"X-Scx-Mode","in":"header","description":"JWT: required when mode isolation is enabled. API key: inherited from the key; a conflicting header is rejected. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeApiKeyResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Merchant"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/sessions":{"get":{"operationId":"MerchantController_listSessions","summary":"List merchant sessions","parameters":[{"name":"X-Scx-Mode","required":false,"in":"header","description":"JWT: required when mode isolation is enabled. API key: inherited from the key; a conflicting header is rejected. Optional during preparation.","schema":{"enum":["live","test"],"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}},{"name":"status","required":false,"in":"query","schema":{}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMerchantSessionsResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Merchant"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]},"post":{"operationId":"MerchantController_createSession","summary":"Create a session from the dashboard","parameters":[{"name":"Idempotency-Key","in":"header","description":"Opaque key per merchant (and per mode after isolation activation), at most 255 characters. The same key and body return the original session.","required":false,"schema":{"type":"string"}},{"name":"X-Scx-Mode","in":"header","description":"JWT: required when mode isolation is enabled. API key: inherited from the key; a conflicting header is rejected. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionResponseDto"}}}},"400":{"description":"`session_idempotency_key_invalid` — The header is present but blank or longer than the limit\n\nBody-validation failures use the same envelope without `code`.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["session_idempotency_key_invalid"]}},"required":["statusCode","message"]}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"409":{"description":"`session_idempotency_conflict` — A key replays the original session only for an identical body; reuse with a different body is refused instead of silently returning an unrelated session","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["session_idempotency_conflict"]}},"required":["statusCode","message","code"]}}}},"422":{"description":"`session_processing_unpayable` — Processing is merchant-paid only and every supported option's current processing price exceeds the merchant's processing expense limit","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["session_processing_unpayable"]},"options":{"type":"array","items":{"type":"object","properties":{"symbol":{"type":"string"},"chainId":{"type":"number"},"networkName":{"type":"string"},"reason":{"type":"string","enum":["exceeds_expense_limit"]},"processingPrice":{"type":"string"},"expenseLimit":{"type":"string"}},"required":["symbol","chainId","networkName","reason","processingPrice","expenseLimit"]}}},"required":["statusCode","message","code"]}}}}},"tags":["Merchant"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/sessions/{id}":{"get":{"operationId":"MerchantController_getSession","summary":"Get one of the merchant's sessions","parameters":[{"name":"id","required":true,"in":"path","description":"Session id (UUID)","schema":{"type":"string"}},{"name":"X-Scx-Mode","in":"header","description":"JWT: required when mode isolation is enabled. API key: inherited from the key; a conflicting header is rejected. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantSessionSummaryDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Merchant"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/sessions/{id}/cancel":{"post":{"operationId":"MerchantController_cancel","summary":"Cancel an unpaid session","description":"Only before any deposit is detected. Repeated cancellation returns the existing outcome.","parameters":[{"name":"id","required":true,"in":"path","description":"Session id (UUID)","schema":{"type":"string"}},{"name":"X-Scx-Mode","in":"header","description":"JWT: required when mode isolation is enabled. API key: inherited from the key; a conflicting header is rejected. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelSessionResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"404":{"description":"Session not found for this merchant"},"409":{"description":"A deposit was detected, the session expired, or settlement already started"}},"tags":["Merchant"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/sessions/{id}/retry-forwarder":{"post":{"operationId":"MerchantController_retryForwarder","summary":"Retry the forwarder run for a session","parameters":[{"name":"id","required":true,"in":"path","description":"Session id (UUID)","schema":{"type":"string"}},{"name":"X-Scx-Mode","in":"header","description":"JWT: required when mode isolation is enabled. API key: inherited from the key; a conflicting header is rejected. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryAcceptedResponseDto"}}}},"400":{"description":"Session is not `failed`, no funded deposit address remains, or the session needs manual recovery"},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"404":{"description":"Session not found for this merchant"},"409":{"description":"A re-execute is already in progress or the session changed concurrently"}},"tags":["Merchant"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/sessions/{id}":{"get":{"operationId":"SessionController_getSession","summary":"Get a payment session","description":"Public — returns the session with payment options and line items. Merchant metadata is never included; read it from GET /v1/merchants/me/sessions/:id or webhook events.","parameters":[{"name":"id","required":true,"in":"path","description":"Session id (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDto"}}}},"404":{"description":"Session not found"}},"tags":["Sessions"]}},"/v1/sessions/{id}/status":{"get":{"operationId":"SessionController_getSessionStatus","summary":"Poll session status","description":"Public — lightweight status + webhookDelivered flag for redirect gating.","parameters":[{"name":"id","required":true,"in":"path","description":"Session id (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStatusResponseDto"}}}},"404":{"description":"Session not found"}},"tags":["Sessions"]}},"/v1/sessions/{id}/cancel":{"post":{"operationId":"SessionController_cancel","summary":"Cancel an unpaid session","description":"Only before any deposit is detected. Repeated cancellation returns the existing outcome.","parameters":[{"name":"id","required":true,"in":"path","description":"Session id (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelSessionResponseDto"}}}},"401":{"description":"Missing or invalid secret API key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"404":{"description":"Session not found for this merchant"},"409":{"description":"A deposit was detected, the session expired, or settlement already started"}},"tags":["Sessions"],"security":[{"sk-api-key":[]}]}},"/v1/sessions":{"post":{"operationId":"SessionController_create","summary":"Create a payment session","description":"Server-to-server — requires an `sk_*` secret key in the Authorization header. When mode isolation is enabled, the key determines the mode and sandboxMode is ignored.","parameters":[{"name":"Idempotency-Key","in":"header","description":"Opaque key (per merchant and, after isolation activation, per mode) (at most 255 characters). A retried create with the same key and body returns the original session instead of creating a new one.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionResponseDto"}}}},"400":{"description":"`session_idempotency_key_invalid` — The header is present but blank or longer than the limit\n\nBody-validation failures use the same envelope without `code`.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["session_idempotency_key_invalid"]}},"required":["statusCode","message"]}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"409":{"description":"`session_idempotency_conflict` — A key replays the original session only for an identical body; reuse with a different body is refused instead of silently returning an unrelated session","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["session_idempotency_conflict"]}},"required":["statusCode","message","code"]}}}},"422":{"description":"`session_processing_unpayable` — Processing is merchant-paid only and every supported option's current processing price exceeds the merchant's processing expense limit","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["session_processing_unpayable"]},"options":{"type":"array","items":{"type":"object","properties":{"symbol":{"type":"string"},"chainId":{"type":"number"},"networkName":{"type":"string"},"reason":{"type":"string","enum":["exceeds_expense_limit"]},"processingPrice":{"type":"string"},"expenseLimit":{"type":"string"}},"required":["symbol","chainId","networkName","reason","processingPrice","expenseLimit"]}}},"required":["statusCode","message","code"]}}}}},"tags":["Sessions"],"security":[{"sk-api-key":[]}]}},"/v1/merchants/me/webhooks":{"post":{"operationId":"WebhookController_create","summary":"Create a webhook endpoint (JWT)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpointRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpointResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]},"get":{"operationId":"WebhookController_list","summary":"List webhook endpoints (JWT)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}},{"name":"includeUnassigned","required":false,"in":"query","description":"Include unassigned endpoints during preparation; ignored after isolation activation","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWebhookEndpointsResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/webhooks/{id}":{"get":{"operationId":"WebhookController_get","summary":"Get a webhook endpoint (JWT)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointSummaryDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]},"patch":{"operationId":"WebhookController_update","summary":"Update a webhook endpoint (JWT)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookEndpointRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointSummaryDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]},"delete":{"operationId":"WebhookController_delete","summary":"Delete a webhook endpoint (JWT)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/webhooks/{id}/rotate-secret":{"post":{"operationId":"WebhookController_rotateSecret","summary":"Rotate a webhook signing secret (JWT)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateWebhookSecretResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/webhooks/{id}/deliveries":{"get":{"operationId":"WebhookController_listDeliveries","summary":"List delivery attempts for an endpoint (JWT)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter deliveries by status; `exhausted` matches deliveries whose retries ran out","schema":{"enum":["pending","dispatching","success","failed","cancelled","exhausted"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWebhookDeliveriesResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/webhooks/{id}/deliveries/{deliveryId}":{"get":{"operationId":"WebhookController_getDelivery","summary":"Inspect a webhook delivery and its retained payload","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"deliveryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryDetailDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/webhooks/{id}/deliveries/{deliveryId}/resend":{"post":{"operationId":"WebhookController_resendDelivery","summary":"Resend any delivery from history","description":"Queues the original event of this delivery to this enabled, subscribed endpoint, with its stable event id and payload retained. One manual attempt; automatic retry timing and budget are unchanged. The same per-event endpoint cooldown and merchant limit apply as for session resend.","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"deliveryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRetryAcceptedResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"404":{"description":"`webhook_event_not_found` — The session has no webhook event yet, or it is not one of your sessions\n\n`webhook_no_enabled_endpoints` — The selected event exists, but no eligible enabled endpoint subscribes to its type","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_event_not_found","webhook_no_enabled_endpoints"]}},"required":["statusCode","message","code"]}}}},"409":{"description":"`webhook_resend_in_progress` — Every eligible endpoint still has a pending or dispatching manual resend of this event","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_resend_in_progress"]}},"required":["statusCode","message","code"]}}}},"429":{"description":"`webhook_resend_too_soon` — Every eligible endpoint had a manual resend of this event queued within the last 60 seconds; retry after that\n\n`webhook_resend_rate_limited` — This resend would take the merchant above 15 manual deliveries queued across all its sessions within the last 60 seconds; retry after that","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_resend_too_soon","webhook_resend_rate_limited"]}},"required":["statusCode","message","code"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/sessions/{id}/retry-webhook":{"post":{"operationId":"WebhookRetryController_retryWebhook","summary":"Resend the latest webhook event of a session (JWT)","description":"Queues one attempt of the session's latest webhook event to every enabled endpoint subscribed to its type, preferring subscribed types among events tied at the latest timestamp, then descending event id. sent on the next worker tick (at-least-once, so a duplicate is possible). Available at any time, including while an automatic retry is scheduled: the manual attempt neither consumes nor shifts the automatic retries, and a failed manual attempt is not retried. Any successful delivery to an endpoint cancels that endpoint's remaining automatic retries. Endpoints that already have a manual resend pending or dispatching, or had one of this event queued in the last 60 seconds, are skipped. A merchant can queue at most 15 manual deliveries across all its sessions per 60 seconds.","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Session id (UUID)","schema":{"type":"string"}}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRetryAcceptedResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"404":{"description":"`webhook_event_not_found` — The session has no webhook event yet, or it is not one of your sessions\n\n`webhook_no_enabled_endpoints` — The selected event exists, but no eligible enabled endpoint subscribes to its type","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_event_not_found","webhook_no_enabled_endpoints"]}},"required":["statusCode","message","code"]}}}},"409":{"description":"`webhook_resend_in_progress` — Every eligible endpoint still has a pending or dispatching manual resend of this event","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_resend_in_progress"]}},"required":["statusCode","message","code"]}}}},"429":{"description":"`webhook_resend_too_soon` — Every eligible endpoint had a manual resend of this event queued within the last 60 seconds; retry after that\n\n`webhook_resend_rate_limited` — This resend would take the merchant above 15 manual deliveries queued across all its sessions within the last 60 seconds; retry after that","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_resend_too_soon","webhook_resend_rate_limited"]}},"required":["statusCode","message","code"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/sessions/{id}/webhook":{"get":{"operationId":"WebhookRetryController_getWebhookStatus","summary":"Delivery status of a session's latest webhook event (JWT or sk_*)","description":"Per endpoint: whether the event was delivered, whether a manual resend is in progress, and when the next automatic attempt is due (attempt N of M).","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Session id (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionWebhookStatusDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"404":{"description":"Session not found for this merchant","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/webhooks":{"post":{"operationId":"WebhookApiController_create","summary":"Create a webhook endpoint (sk_*)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpointRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpointResponseDto"}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]},"get":{"operationId":"WebhookApiController_list","summary":"List webhook endpoints (sk_*)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}},{"name":"includeUnassigned","required":false,"in":"query","description":"Include unassigned endpoints during preparation; ignored after isolation activation","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWebhookEndpointsResponseDto"}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]}},"/v1/webhooks/{id}":{"get":{"operationId":"WebhookApiController_get","summary":"Get a webhook endpoint (sk_*)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointSummaryDto"}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]},"patch":{"operationId":"WebhookApiController_update","summary":"Update a webhook endpoint (sk_*)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookEndpointRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointSummaryDto"}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]},"delete":{"operationId":"WebhookApiController_delete","summary":"Delete a webhook endpoint (sk_*)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]}},"/v1/webhooks/{id}/rotate-secret":{"post":{"operationId":"WebhookApiController_rotateSecret","summary":"Rotate a webhook signing secret (sk_*)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateWebhookSecretResponseDto"}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]}},"/v1/webhooks/{id}/deliveries":{"get":{"operationId":"WebhookApiController_listDeliveries","summary":"List delivery attempts for an endpoint (sk_*)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter deliveries by status; `exhausted` matches deliveries whose retries ran out","schema":{"enum":["pending","dispatching","success","failed","cancelled","exhausted"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWebhookDeliveriesResponseDto"}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]}},"/v1/webhooks/{id}/deliveries/{deliveryId}":{"get":{"operationId":"WebhookApiController_getDelivery","summary":"Inspect a webhook delivery and its retained payload","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"deliveryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryDetailDto"}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]}},"/v1/webhooks/{id}/deliveries/{deliveryId}/resend":{"post":{"operationId":"WebhookApiController_resendDelivery","summary":"Resend any delivery from history","description":"Queues the original event of this delivery to this enabled, subscribed endpoint, with its stable event id and payload retained. One manual attempt; automatic retry timing and budget are unchanged. The same per-event endpoint cooldown and merchant limit apply as for session resend.","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"deliveryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRetryAcceptedResponseDto"}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"404":{"description":"`webhook_event_not_found` — The session has no webhook event yet, or it is not one of your sessions\n\n`webhook_no_enabled_endpoints` — The selected event exists, but no eligible enabled endpoint subscribes to its type","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_event_not_found","webhook_no_enabled_endpoints"]}},"required":["statusCode","message","code"]}}}},"409":{"description":"`webhook_resend_in_progress` — Every eligible endpoint still has a pending or dispatching manual resend of this event","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_resend_in_progress"]}},"required":["statusCode","message","code"]}}}},"429":{"description":"`webhook_resend_too_soon` — Every eligible endpoint had a manual resend of this event queued within the last 60 seconds; retry after that\n\n`webhook_resend_rate_limited` — This resend would take the merchant above 15 manual deliveries queued across all its sessions within the last 60 seconds; retry after that","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_resend_too_soon","webhook_resend_rate_limited"]}},"required":["statusCode","message","code"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]}},"/v1/sessions/{id}/retry-webhook":{"post":{"operationId":"WebhookApiRetryController_retryWebhook","summary":"Resend the latest webhook event of a session (sk_*)","description":"Queues one attempt of the session's latest webhook event to every enabled endpoint subscribed to its type, preferring subscribed types among events tied at the latest timestamp, then descending event id. sent on the next worker tick (at-least-once, so a duplicate is possible). Available at any time, including while an automatic retry is scheduled: the manual attempt neither consumes nor shifts the automatic retries, and a failed manual attempt is not retried. Any successful delivery to an endpoint cancels that endpoint's remaining automatic retries. Endpoints that already have a manual resend pending or dispatching, or had one of this event queued in the last 60 seconds, are skipped. A merchant can queue at most 15 manual deliveries across all its sessions per 60 seconds.","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for JWT requests when mode isolation is enabled; API keys inherit their mode. Optional during preparation.","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Session id (UUID)","schema":{"type":"string"}}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRetryAcceptedResponseDto"}}}},"401":{"description":"Missing or unknown `Authorization: Bearer sk_*` secret key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"404":{"description":"`webhook_event_not_found` — The session has no webhook event yet, or it is not one of your sessions\n\n`webhook_no_enabled_endpoints` — The selected event exists, but no eligible enabled endpoint subscribes to its type","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_event_not_found","webhook_no_enabled_endpoints"]}},"required":["statusCode","message","code"]}}}},"409":{"description":"`webhook_resend_in_progress` — Every eligible endpoint still has a pending or dispatching manual resend of this event","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_resend_in_progress"]}},"required":["statusCode","message","code"]}}}},"429":{"description":"`webhook_resend_too_soon` — Every eligible endpoint had a manual resend of this event queued within the last 60 seconds; retry after that\n\n`webhook_resend_rate_limited` — This resend would take the merchant above 15 manual deliveries queued across all its sessions within the last 60 seconds; retry after that","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"},"code":{"type":"string","enum":["webhook_resend_too_soon","webhook_resend_rate_limited"]}},"required":["statusCode","message","code"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]}},"/v1/paymaster/clients":{"get":{"operationId":"PaymasterClientsController_list","summary":"List paymaster clients","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPaymasterClientsResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Clients"],"security":[{"merchant-jwt":[]}]},"post":{"operationId":"PaymasterClientsController_create","summary":"Create a paymaster client","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePaymasterClientRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePaymasterClientResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Clients"],"security":[{"merchant-jwt":[]}]}},"/v1/paymaster/clients/{id}":{"patch":{"operationId":"PaymasterClientsController_update","summary":"Update a paymaster client","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Paymaster client id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePaymasterClientRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymasterClientSummaryDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Clients"],"security":[{"merchant-jwt":[]}]},"delete":{"operationId":"PaymasterClientsController_revoke","summary":"Revoke a paymaster client","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Paymaster client id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymasterClientSummaryDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Clients"],"security":[{"merchant-jwt":[]}]}},"/v1/paymaster/allowlist":{"get":{"operationId":"ContractAllowlistController_list","summary":"List allowlisted contracts","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListContractAllowlistResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Allowlist"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]},"post":{"operationId":"ContractAllowlistController_upsert","summary":"Add or update an allowlisted contract","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContractAllowlistRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractAllowlistEntryDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Allowlist"],"security":[{"merchant-jwt":[]}]}},"/v1/paymaster/allowlist/{id}":{"delete":{"operationId":"ContractAllowlistController_remove","summary":"Remove an allowlisted contract","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Allowlist entry id","schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Allowlist"],"security":[{"merchant-jwt":[]}]}},"/v1/paymaster/limits":{"get":{"operationId":"SpendLimitsController_get","summary":"Current sponsorship limits: platform, merchant, effective","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpendLimitsResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Spend Limits"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]},"patch":{"operationId":"SpendLimitsController_update","summary":"Tighten sponsorship limits (null clears a limit back to the platform default)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSpendLimitsRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpendLimitsResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Spend Limits"],"security":[{"merchant-jwt":[]}]}},"/v1/paymaster/deny-rules":{"get":{"operationId":"DenyRuleController_list","summary":"List deny rules (senders and targets)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDenyRulesResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Deny Rules"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]},"post":{"operationId":"DenyRuleController_upsert","summary":"Add or update a deny rule","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDenyRuleRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DenyRuleEntryDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Deny Rules"],"security":[{"merchant-jwt":[]}]}},"/v1/paymaster/deny-rules/{id}":{"delete":{"operationId":"DenyRuleController_remove","summary":"Remove a deny rule","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","description":"Deny rule id","schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Deny Rules"],"security":[{"merchant-jwt":[]}]}},"/v1/paymaster/rpc":{"post":{"operationId":"PaymasterRpcController_handle","summary":"ERC-4337 paymaster JSON-RPC proxy","description":"ERC-4337 paymaster JSON-RPC for the publishable `pmc_*` client id in `X-Client-Id`.\n\n**Methods.** Every method takes `params = [userOp, entryPoint, chainId, context?]`: `entryPoint` is EntryPoint v0.8, v0.7 or v0.6; `chainId` is a `0x` hex string, a decimal string or a number; `context` is optional `{\"token\": \"0x…\"}`.\n\n- `pm_getPaymasterStubData` (ERC-7677) — paymaster data with a recoverable, non-authorizing 65-byte ECDSA placeholder for gas estimation; does not call the real signer or authorize payment, and reads the limits without consuming them.\n- `pm_getPaymasterData` (ERC-7677) — signed paymaster data to submit; needs `callGasLimit`, `verificationGasLimit`, `preVerificationGas` and `maxFeePerGas`, and consumes one unit of the per-sender limits. A request whose `verificationGasLimit` and `preVerificationGas` are both zero cannot be included on-chain, so it is answered like `pm_getPaymasterStubData`: a non-authorizing placeholder signature, limits read but not consumed.\n- `pm_sponsorUserOperation` — the same signed result for merchant-sponsored gas; a request with zero `verificationGasLimit` and `preVerificationGas` is answered like the stub the same way; a `context.token` is refused.\n\nV0.6 requests use unpacked `initCode` and `paymasterAndData`; split factory/paymaster gas fields and EIP-7702 are refused. V0.6 returns `{paymasterAndData}`. V0.7/v0.8 return `{paymaster, paymasterData, paymasterVerificationGasLimit, paymasterPostOpGasLimit}`.\n\n**What gets sponsored.**\n- A `pmc_live_*` key covers mainnets only and a `pmc_test_*` key testnets only; the chain must also be in the client's `allowedChainIds`.\n- No `context.token` is merchant-sponsored gas; a `context.token` is user-paid gas in that ERC-20. The client's `gasMode` (`sponsored`, `user_paid`, `both`) decides which are allowed.\n- Direct calls support `execute(address,uint256,bytes)` and MetaMask's single `execute((address,uint256,bytes))`. The target must be on the merchant contract allowlist and not blocked by a deny rule.\n- Direct batches support `executeBatch(address[],uint256[],bytes[])` (SimpleAccount v0.7 and thirdweb Account on supported EntryPoints, including thirdweb v0.6) and ERC-7579 `execute(bytes32,bytes)` with exactly the BatchDefault mode (`0x01` then 31 zero bytes) and an `abi.encode((address,uint256,bytes)[])` payload (MetaMask smart accounts). A batch holds 1 to 16 calls in at most 32 KiB of `callData`, every call has zero native value, the three `executeBatch` arrays have equal length (an empty value array is refused), and the encoding must be canonical. Try, delegatecall and every other mode, SimpleAccount v0.8 `executeBatch((address,uint256,bytes)[])` and a call targeting DelegationManager are refused.\n- Every call target of a batch must be on the merchant contract allowlist and none may be blocked by a deny rule; one refused call refuses the whole operation before it is signed or counted against limits, and the error names the call by its zero-based index. The allowlist matches contract addresses only; call arguments such as an `approve` spender are not checked.\n- A batch executes in the account in order and atomically: a reverting call reverts every call of the operation, while the included operation still consumes gas and is billed like any other operation. A batch is one operation for limits, billing and usage; `targets` on usage and activity rows lists every call target in order.\n- On all supported networks (Ethereum, Base, Arbitrum and their Sepolia testnets), MetaMask v1.3.0 Advanced Permissions (ERC-7715) support one ERC-20 allowance transfer through DelegationManager, wrapped in a supported single execute call or ERC-7579 `execute(bytes32,bytes)` with an all-zero SingleDefault mode. One root delegation must bind the sender and chain-specific EOA signature, token allowance, expiry, redeemer, payee, zero native value and nonce. Delegated batches, redelegation, other modes and unrecognised caveats are refused.\n- Delegated transfers check deny rules and per-account limits for both the session sender and original owner; the global budget is charged once. Usage keeps the actual UserOperation sender and records the owner in `reason`. Bundler execution simulation checks on-chain revocation and remaining allowance.\n- Sponsored ops on mainnets need a positive prepaid gas balance.\n- Per-sender limits are the lower of the platform and merchant values, see `GET /v1/paymaster/limits`.\n\n**Errors.**\n\n| Response | `message` starts with | Cause |\n| --- | --- | --- |\n| HTTP 401 (`/v1/paymaster/rpc`, `/v1/paymaster/bundler/{chainId}`) | `paymaster_unauthorized` | Client id missing (`X-Client-Id` header or `?clientId=`), unknown or revoked |\n| HTTP 403 (`/v1/paymaster/rpc`, `/v1/paymaster/bundler/{chainId}`) | `paymaster_origin_not_allowed` | The client has `allowedOrigins` and the `Origin` header is missing or not on the list |\n| JSON-RPC `-32700` | `Parse error` | The JSON body is not a JSON-RPC 2.0 request: `jsonrpc` is not `\"2.0\"`, `method` is not a string, `params` is not an array, or `id` is not a string or number |\n| JSON-RPC `-32601` | `Unknown method` | `method` is not `pm_sponsorUserOperation`, `pm_getPaymasterStubData` or `pm_getPaymasterData` |\n| JSON-RPC `-32602` | `Invalid params` | `params[0]` is not an object, `params[1]` is not a string starting with `0x`, `params[2]` is not a chainId (`0x` hex, decimal string or number), or `nonce` or a gas field cannot be read as an integer |\n| JSON-RPC `-32602` | `paymaster_token_invalid` | `params[3].token` is present but not an address |\n| JSON-RPC `-32602` | `paymaster_token_unsupported_method` | `context.token` sent with `pm_sponsorUserOperation`; user-paid gas uses the stub + data methods |\n| JSON-RPC `-32602` | `paymaster_gas_fields_missing` | `pm_getPaymasterData` / `pm_sponsorUserOperation` without `callGasLimit`, `verificationGasLimit`, `preVerificationGas` or `maxFeePerGas` |\n| HTTP 403 (`/v1/paymaster/rpc`, `/v1/paymaster/bundler/{chainId}`); JSON-RPC `-32602` | `Policy denied: paymaster_chain_not_allowed` (`paymaster_chain_not_allowed` on the bundler route) | chainId is not in the client's `allowedChainIds`; on `/v1/paymaster/rpc` the client-id check answers HTTP 403 first, the JSON-RPC code is the service's re-check |\n| HTTP 403 (`/v1/paymaster/bundler/{chainId}`); JSON-RPC `-32602` | `Policy denied: paymaster_key_network_class_mismatch` (`paymaster_key_network_class_mismatch` on the bundler route) | A `pmc_live_*` key on a testnet or a `pmc_test_*` key on a mainnet |\n| JSON-RPC `-32602` | `Policy denied: paymaster_entrypoint_not_supported` | `params[1]` is not a supported EntryPoint (v0.6, v0.7, v0.8) |\n| JSON-RPC `-32602` | `Policy denied: paymaster_target_not_allowed` | Unsupported execution, batch or bounded MetaMask delegation transfer, a batch call with native value or targeting DelegationManager, invalid delegation permission, or a call target is not in the merchant's contract allowlist for that chain |\n| HTTP 403 (`/v1/paymaster/bundler/{chainId}`); JSON-RPC `-32600` | `Policy denied: paymaster_gas_mode_not_allowed` (`paymaster_gas_mode_not_allowed` on the bundler route) | The client's `gasMode` does not allow this op (a `token` on a `sponsored` key, no token on a `user_paid` key) |\n| JSON-RPC `-32600` | `Policy denied: paymaster_blocked_by_merchant_rule` | A merchant deny rule matches the sender, the delegated owner or any call target on that chain; checked before the allowlist |\n| HTTP 402 (`/v1/paymaster/bundler/{chainId}`); JSON-RPC `-32600` | `Policy denied: paymaster_billing_balance_exhausted` (`paymaster_billing_balance_exhausted` on the bundler route) | Sponsored op on a mainnet while the merchant's prepaid gas balance is exhausted |\n| JSON-RPC `-32600` | `Policy denied: paymaster_merchant_tx_cap_unpriceable` | A merchant per-transaction cap is set and the op cannot be priced (no ETH/USD rate) |\n| JSON-RPC `-32600` | `Policy denied: paymaster_merchant_tx_cap_exceeded` | Estimated cost plus markup exceeds the merchant per-transaction cap |\n| JSON-RPC `-32600` | `Policy denied: paymaster_global_cap_exceeded` | Platform daily sponsorship budget reached; resets at 00:00 UTC |\n| JSON-RPC `-32600` | `Policy denied: paymaster_spend_cap_exceeded` | Per-sender daily USD cap reached; `(merchant-configured cap)` suffix when the merchant cap is the binding one |\n| JSON-RPC `-32600` | `Policy denied: paymaster_rate_limit_exceeded` | Per-sender hourly op limit reached; `(merchant-configured cap)` suffix when the merchant limit is the binding one |\n| JSON-RPC `-32600` | `Policy denied: paymaster_price_unavailable` | A dollar cap applies and no ETH/USD price is available; retry |\n| JSON-RPC `-32603` | `paymaster_upstream_error` | The signing service is unreachable, timed out, or answered with a non-2xx status or a non-JSON body |\n| JSON-RPC `-32603` | `paymaster_mode_mismatch` | A `token` was requested and the signing service did not return ERC-20 mode paymaster data |\n| HTTP 502 (`/v1/paymaster/bundler/{chainId}`) | `bundler upstream` | The platform bundler answered with a non-2xx status or a non-JSON body; a transport failure returns 502 with the transport error text instead |\n\n- HTTP 401 and 403 from the client-id check carry `{\"statusCode\":<status>,\"message\":\"...\",\"error\":\"...\"}`; the other HTTP errors of the bundler route carry `{\"error\":{\"message\":\"...\",\"type\":\"error\"}}`.\n- A `{chainId}` path segment that is not an integer is rejected with HTTP 400 `Validation failed (numeric string is expected)` right after the client-id check.\n- JSON-RPC errors arrive with HTTP 200 as `{\"jsonrpc\":\"2.0\",\"id\":<id>,\"error\":{\"code\":<code>,\"message\":\"...\"}}`; `id` is `null` only for `Parse error`.\n- A `Policy denied: ` prefix marks a policy decision: never fall back to another paymaster for that operation. The bundler route never adds the prefix.\n- Once every check passes, errors from the internal signing service (for example `Unsupported chain`, `Token … not whitelisted`, `Paymaster deposit too low`) are returned unchanged with code `-32602` or `-32000`.","parameters":[{"name":"Origin","in":"header","description":"Validated against the client's allowedOrigins when configured","required":false,"schema":{"type":"string"}},{"name":"X-Client-Id","in":"header","description":"Publishable paymaster client id (`pmc_live_*` / `pmc_test_*`)","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponseDto"}}}},"401":{"description":"`paymaster_unauthorized` — Client id missing (`X-Client-Id` header or `?clientId=`), unknown or revoked","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"403":{"description":"`paymaster_origin_not_allowed` — The client has `allowedOrigins` and the `Origin` header is missing or not on the list\n\n`paymaster_chain_not_allowed` — chainId is not in the client's `allowedChainIds`; on `/v1/paymaster/rpc` the client-id check answers HTTP 403 first, the JSON-RPC code is the service's re-check","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster RPC"],"security":[{"paymaster-client-id":[]}]}},"/v1/paymaster/bundler/{chainId}":{"post":{"operationId":"PaymasterBundlerController_proxy","summary":"Authenticated ERC-4337 bundler proxy","description":"Relays ERC-4337 bundler JSON-RPC (e.g. `eth_sendUserOperation`) to the platform bundler so the Pimlico key never reaches the browser. Authenticates via the publishable `pmc_*` client id in `X-Client-Id` (Origin validated against the client's allowlist); the `:chainId` path param is validated against the client's allowedChainIds.","parameters":[{"name":"chainId","required":true,"in":"path","schema":{"type":"number"}},{"name":"Origin","in":"header","description":"Validated against the client's allowedOrigins when configured","required":false,"schema":{"type":"string"}},{"name":"clientId","required":false,"in":"query","description":"Publishable client id, alternative to the `X-Client-Id` header (header wins).","schema":{}},{"name":"X-Client-Id","in":"header","description":"Publishable paymaster client id (`pmc_live_*` / `pmc_test_*`). May be supplied as the `clientId` query param instead — thirdweb's `bundlerUrl` can't send a header, so the bundler route accepts it in the URL.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"description":"ERC-4337 bundler JSON-RPC request, or a batch of them","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/BundlerJsonRpcRequestDto"},{"type":"array","items":{"$ref":"#/components/schemas/BundlerJsonRpcRequestDto"}}]}}}},"responses":{"200":{"description":"Raw bundler JSON-RPC response"},"400":{"description":"`Validation failed (numeric string is expected)` — the `{chainId}` path segment is not an integer","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"401":{"description":"`paymaster_unauthorized` — Client id missing (`X-Client-Id` header or `?clientId=`), unknown or revoked","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}},"402":{"description":"`paymaster_billing_balance_exhausted` — Sponsored op on a mainnet while the merchant's prepaid gas balance is exhausted","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string","enum":["error"]}},"required":["message","type"]}},"required":["error"]}}}},"403":{"description":"`paymaster_origin_not_allowed` — The client has `allowedOrigins` and the `Origin` header is missing or not on the list\n\n`paymaster_chain_not_allowed` — chainId is not in the client's `allowedChainIds`; on `/v1/paymaster/rpc` the client-id check answers HTTP 403 first, the JSON-RPC code is the service's re-check\n\n`paymaster_key_network_class_mismatch` — A `pmc_live_*` key on a testnet or a `pmc_test_*` key on a mainnet\n\n`paymaster_gas_mode_not_allowed` — The client's `gasMode` does not allow this op (a `token` on a `sponsored` key, no token on a `user_paid` key)","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string","enum":["error"]}},"required":["message","type"]}},"required":["error"]},{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}]}}}},"502":{"description":"`bundler upstream` — The platform bundler answered with a non-2xx status or a non-JSON body; a transport failure returns 502 with the transport error text instead","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string","enum":["error"]}},"required":["message","type"]}},"required":["error"]}}}}},"tags":["Paymaster Bundler"],"security":[{"paymaster-client-id":[]}]}},"/v1/paymaster/usage":{"get":{"operationId":"UsageController_list","summary":"List sponsored-op usage (cursor-paginated)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"cursor","required":false,"in":"query","schema":{}},{"name":"clientId","required":false,"in":"query","schema":{}},{"name":"chainId","required":false,"in":"query","schema":{}},{"name":"networkMode","required":false,"in":"query","description":"Filter by the recorded chain network class","schema":{"enum":["live","test"],"type":"string"}},{"name":"gasMode","required":false,"in":"query","schema":{"enum":["sponsored","user_paid"],"type":"string"}},{"name":"mode","required":false,"in":"query","deprecated":true,"description":"Gas payment mode; use gasMode","schema":{"enum":["sponsored","user_paid"],"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"enum":["denied_target","denied_upstream","denied_billing_balance","denied_merchant_limit","denied_gas_mode","denied_chain","denied_entrypoint","denied_origin","denied_malformed","denied_rate_limit","denied_spend_cap","denied_global_cap","denied_price_unavailable","submitted","onchain_success","onchain_reverted","dropped","denied_merchant_rule"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListUsageResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Usage"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/paymaster/overview":{"get":{"operationId":"MerchantOverviewController_get","summary":"Merchant-scoped paymaster overview","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"window","required":false,"in":"query","description":"Defaults to 24h; an unknown value falls back to 24h","schema":{"enum":["24h","7d","30d","all"],"type":"string"}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantPaymasterOverviewResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Activity"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/paymaster/overview/recent-ops":{"get":{"operationId":"MerchantOverviewController_recent","summary":"Merchant's recent sponsored ops","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"limit","required":false,"in":"query","description":"1–100, default 20","schema":{"type":"string"}},{"name":"mode","required":false,"in":"query","schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MerchantPaymasterRecentOpDto"}}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Activity"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/paymaster/activity":{"get":{"operationId":"MerchantActivityController_list","summary":"Unified merchant paymaster activity (cursor-paginated)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"Required for scoped JWT requests at isolation activation; inherited from API keys","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"1–200, default 50","schema":{}},{"name":"cursor","required":false,"in":"query","description":"`nextCursor` of the previous page","schema":{}},{"name":"networkMode","required":false,"in":"query","description":"Filter by the recorded chain network class","schema":{"enum":["live","test"],"type":"string"}},{"name":"gasMode","required":false,"in":"query","schema":{"enum":["sponsored","user_paid"],"type":"string"}},{"name":"mode","required":false,"in":"query","deprecated":true,"description":"Gas payment mode; use gasMode","schema":{"enum":["sponsored","user_paid"],"type":"string"}},{"name":"chainId","required":false,"in":"query","schema":{}},{"name":"status","required":false,"in":"query","schema":{"enum":["denied_target","denied_upstream","denied_billing_balance","denied_merchant_limit","denied_gas_mode","denied_chain","denied_entrypoint","denied_origin","denied_malformed","denied_rate_limit","denied_spend_cap","denied_global_cap","denied_price_unavailable","submitted","onchain_success","onchain_reverted","dropped","denied_merchant_rule"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMerchantActivityResponseDto"}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Paymaster Activity"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/balance":{"get":{"operationId":"MerchantBalanceController_summary","summary":"Live prepaid balance or informational Test cost estimates","parameters":[{"name":"X-Scx-Mode","in":"header","description":"At mode isolation activation this carrier is required for JWT requests and inherited from API keys. Test selects informational cost estimates, never a monetary balance.","required":false,"schema":{"enum":["test","live"],"type":"string"}},{"name":"mode","required":false,"in":"query","description":"Optional filter agreeing with the mode carrier; Test selects estimates; Live selects monetary billing","schema":{"enum":["test","live"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["balanceUsdMicros","reservedUsdMicros","totalToppedUpUsdMicros","markupBps","billingEnabled","currentPeriod"],"properties":{"mode":{"type":"string","enum":["live"]},"balanceUsdMicros":{"type":"string"},"reservedUsdMicros":{"type":"string"},"totalToppedUpUsdMicros":{"type":"string"},"markupBps":{"type":"integer"},"billingEnabled":{"type":"boolean"},"currentPeriod":{"type":"object","properties":{"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"},"gasUsdMicros":{"type":"string"},"markupUsdMicros":{"type":"string"},"totalUsdMicros":{"type":"string"},"chargeCount":{"type":"integer"},"pendingPriceCount":{"type":"integer"}}}}},{"type":"object","additionalProperties":false,"required":["mode","billing","markupBps","currentPeriod"],"properties":{"mode":{"type":"string","enum":["test"]},"billing":{"type":"string","enum":["estimate_only"]},"markupBps":{"type":"integer"},"currentPeriod":{"type":"object","properties":{"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"},"gasUsdMicros":{"type":"string"},"markupUsdMicros":{"type":"string"},"estimatedUsdMicros":{"type":"string"},"operationCount":{"type":"integer"},"pendingPriceCount":{"type":"integer"}}}}}]}}}},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Harness Balance"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/balance/charges":{"get":{"operationId":"MerchantBalanceController_charges","summary":"Live gas charges or Test cost estimates (cursor-paginated)","parameters":[{"name":"X-Scx-Mode","in":"header","description":"At mode isolation activation this carrier is required for JWT requests and inherited from API keys. Test selects informational cost estimates, never a monetary balance.","required":false,"schema":{"enum":["test","live"],"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"cursor","required":false,"in":"query","schema":{}},{"name":"chainId","required":false,"in":"query","schema":{}},{"name":"mode","required":false,"in":"query","description":"Optional filter agreeing with the mode carrier; Test selects estimates; Live selects monetary billing","schema":{"enum":["test","live"],"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Harness Balance"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/balance/charges.csv":{"get":{"operationId":"MerchantBalanceController_chargesCsv","summary":"Charge history as CSV over a UTC date range, oldest first","parameters":[{"name":"X-Scx-Mode","in":"header","description":"At mode isolation activation this carrier is required for JWT requests and inherited from API keys. Test selects informational cost estimates, never a monetary balance.","required":false,"schema":{"enum":["test","live"],"type":"string"}},{"name":"from","required":true,"in":"query","description":"UTC date YYYY-MM-DD, inclusive","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","description":"UTC date YYYY-MM-DD, inclusive","schema":{"type":"string"}},{"name":"chainId","required":false,"in":"query","schema":{"type":"string"}},{"name":"mode","required":false,"in":"query","description":"Optional filter agreeing with the mode carrier; Test selects estimates; Live selects monetary billing","schema":{"enum":["test","live"],"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Harness Balance"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/balance/statement.pdf":{"get":{"operationId":"MerchantBalanceController_statementPdf","summary":"Monthly statement as PDF; a month becomes available shortly after it closes","parameters":[{"name":"X-Scx-Mode","in":"header","description":"At mode isolation activation this carrier is required for JWT requests and inherited from API keys. Test selects informational cost estimates, never a monetary balance.","required":false,"schema":{"enum":["test","live"],"type":"string"}},{"name":"month","required":true,"in":"query","description":"UTC calendar month, YYYY-MM","schema":{"type":"string"}},{"name":"mode","required":false,"in":"query","description":"Optional filter agreeing with the mode carrier; Test selects estimates; Live selects monetary billing","schema":{"enum":["test","live"],"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Harness Balance"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/balance/topups":{"get":{"operationId":"MerchantBalanceController_listTopUps","summary":"Balance top-ups, newest first","parameters":[{"name":"X-Scx-Mode","in":"header","description":"At mode isolation activation this carrier is required for JWT requests and inherited from API keys. Test selects informational cost estimates, never a monetary balance.","required":false,"schema":{"enum":["test","live"],"type":"string"}},{"name":"mode","required":false,"in":"query","description":"Optional filter agreeing with the mode carrier; Test selects estimates; Live selects monetary billing","schema":{"enum":["test","live"],"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Harness Balance"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]},"post":{"operationId":"MerchantBalanceController_createTopUp","summary":"Create a self-serve top-up payment session","parameters":[{"name":"X-Scx-Mode","in":"header","description":"At mode isolation activation this carrier is required for JWT requests and inherited from API keys. Test selects informational cost estimates, never a monetary balance.","required":false,"schema":{"enum":["test","live"],"type":"string"}}],"responses":{"201":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Harness Balance"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/yield-deployments/deploy-options":{"get":{"operationId":"YieldDeploymentController_deployOptions","summary":"Get the network's vault deployment settings and permitted tokens","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/yield-deployments/contract-sets":{"get":{"operationId":"YieldDeploymentController_contractSets","summary":"List deployed contract sets belonging to the merchant on a network","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]}},"/v1/merchants/me/yield-deployments/{id}/contracts":{"post":{"operationId":"YieldDeploymentController_linkContracts","summary":"Link an existing contract set to an unconfigured draft, or switch a live site to another of the merchant's vaults","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/yield-deployments":{"get":{"operationId":"YieldDeploymentController_list","summary":"List the merchant's yield deployments","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"X-Scx-Mode","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]},"post":{"operationId":"YieldDeploymentController_create","summary":"Create a yield deployment","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}}],"responses":{"201":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/yield-deployments/{id}":{"get":{"operationId":"YieldDeploymentController_findOne","summary":"Get a yield deployment","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]},{"sk-api-key":[]}]},"patch":{"operationId":"YieldDeploymentController_update","summary":"Update a yield deployment's name or branding","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]},"delete":{"operationId":"YieldDeploymentController_remove","summary":"Delete a draft yield deployment","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/yield-deployments/{id}/deploy":{"post":{"operationId":"YieldDeploymentController_deploy","summary":"Queue the on-chain deployment of a yield deployment's vault","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"202":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/yield-deployments/{id}/sunset":{"post":{"operationId":"YieldDeploymentController_sunset","summary":"Retire a yield deployment from the merchant's active list","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]},"delete":{"operationId":"YieldDeploymentController_unsunset","summary":"Return a sunset yield deployment to the active list","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/yield-deployments/{id}/domains":{"post":{"operationId":"YieldDeploymentController_addDomain","summary":"Attach a custom domain to a yield deployment","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/yield-deployments/{id}/domains/{domainId}":{"delete":{"operationId":"YieldDeploymentController_removeDomain","summary":"Remove a custom domain from a yield deployment","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"domainId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT, or an invalid `sk_*` key where the operation accepts one","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/yield-deployments/{id}/logo":{"post":{"operationId":"YieldLogoController_uploadLogo","summary":"Upload the logo of a yield deployment","parameters":[{"name":"X-Scx-Mode","in":"header","description":"JWT mode is required at isolation activation; API keys inherit their mode","required":false,"schema":{"enum":["live","test"],"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"201":{"description":""},"401":{"description":"Missing, malformed or expired merchant JWT","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["yield-deployments"],"security":[{"merchant-jwt":[]}]}}},"info":{"title":"StablecoinX API","description":"Managed API for StablecoinX — stablecoin payment sessions, merchant dashboard, webhooks, and the shared ERC-4337 paymaster. The merchant dashboard uses a SIWE-issued JWT; an `sk_*` secret key reads the merchant's own data, creates sessions and manages webhooks — every operation lists the credentials it accepts, and minting or listing credentials requires the JWT. The paymaster RPC proxy uses a publishable `pmc_*` client id in the `X-Client-Id` header.\n\n## Webhook delivery\n\nEndpoints and delivery history are managed under `/v1/webhooks` with an `sk_*` secret key — see the [Webhooks routes](https://api.dev.scx.easeflow.io/docs#/Webhooks) in the full OpenAPI ([JSON](https://api.dev.scx.easeflow.io/docs/openapi.json)).\n\n- **At-least-once.** Every recorded event is delivered at least once to each endpoint that was subscribed when the event was recorded, as long as the endpoint answers 2xx within the automatic retry window. A delivery whose endpoint is disabled, or whose URL fails the dispatch-time check, is marked `failed` without retry; a DNS resolution failure or a signing secret that cannot be decrypted is a failed attempt and follows the automatic retry schedule; a manual resend (`POST /v1/sessions/{id}/retry-webhook` or the dashboard) reaches only the session's latest event, sent to the endpoints enabled and subscribed to its type at resend time — an endpoint added later can receive an older event, and `POST /v1/webhooks/{id}/deliveries/{deliveryId}/resend` replays any retained delivery, its stored payload unchanged, to its original endpoint, which must still be enabled and subscribed to the event type. The same event can arrive more than once: a 2xx that did not reach StablecoinX (timeout, dropped connection), a worker failure after your 2xx, or a manual resend, which sends the event again even after a successful delivery.\n- **No ordering guarantee.** Events of one session can arrive in any order — a retried `session.confirming` can arrive after `session.completed`.\n- **Session status and resend.** Both select the same latest event. Events co-produced by one payment share a timestamp; tied events prefer types subscribed to by an enabled endpoint, then descending event id. Selection never falls back to an earlier timestamp. Use delivery history to inspect or replay other retained events.\n- **Stable event id.** Every event has an id `evt_*` in the body's `id`, copied to the `X-StablecoinX-Event-Id` header. It is identical on every delivery of that event and on every endpoint the event is sent to.\n- **Dedupe on the body `id` after verifying the signature.** `X-StablecoinX-Signature` covers `{timestamp}.{rawBody}` only; the `X-StablecoinX-Event-Id` header is unsigned.\n- **Recommended handler:** verify the signature → in one database transaction insert the event id into a table with a UNIQUE constraint together with your own state change (or a job row) → commit → respond 2xx → run external side effects (emails, outbound calls) from the job, idempotently. On a unique-key conflict respond 2xx without re-running anything. When several endpoints share one store, key the table on the consuming system and the event id. Respond within 10 seconds: a slower response times out and is retried.\n- **Ordering:** treat an event as a signal, not as the state. From the job, not the request path, re-read the session with `GET /v1/merchants/me/sessions/{id}` (`sk_*`, full OpenAPI) and act on its current `status` and `amountReceivedByChain`; do not order events by their bodies or `createdAt`. Never move an order back from `completed`; `session.expired` can still be followed by `session.completed`.\n- **Retention:** keep processed event ids for as long as you need to suppress repeated side effects — any retained delivery, including a balance event, can be manually replayed at any time.\n\n## floYsh / Yield as a Service\n\nfloYsh is StablecoinX's Yield as a Service (YaaS): a branded stablecoin-yield site built around Ethena USDe/sUSDe vaults. Merchants manage the site's deployment, branding and domains in Business UI; customers use the public site to connect a wallet and access the vault.\n\n- [Business UI](https://business.dev.scx.easeflow.io/) — sign in, open **Deployments → Yield** (`/deployments/yield`), and choose **New deployment** (or **Create deployment** for the first one). Open a deployment to edit its branding, manage **Domains**, and inspect **Contracts**.\n- [Business UI guide](https://business.dev.scx.easeflow.io/llms-full.txt) — product overview and navigation, including how to find a deployment's public site.\n- [Merchant OpenAPI](https://api.dev.scx.easeflow.io/docs#/yield-deployments) ([JSON](https://api.dev.scx.easeflow.io/docs/openapi.json)) — configuration routes under `/v1/merchants/me/yield-deployments`, authenticated with a merchant JWT; the list and read routes also accept an `sk_*` secret key. These routes are in the full merchant spec, not the integrator spec at `/openapi`.\n\nThe MCP server currently has no yield-deployment tools; guide users to Business UI for floYsh management.\n","version":"1.0","contact":{}},"tags":[{"name":"Health","description":"Liveness probe"},{"name":"Auth","description":"Merchant authentication — SIWE login payload + verify → JWT"},{"name":"Sessions","description":"Payment sessions — create (sk_*), read + poll status (public)"},{"name":"Merchant","description":"Merchant account — profile, API keys, sessions (JWT; profile and session reads and retry-forwarder also sk_*)"},{"name":"Webhooks","description":"Webhook endpoint CRUD + delivery history (sk_* / JWT)"},{"name":"Paymaster RPC","description":"ERC-4337 paymaster JSON-RPC proxy (X-Client-Id)"},{"name":"Paymaster Bundler","description":"ERC-4337 bundler JSON-RPC proxy per chain (X-Client-Id or ?clientId=)"},{"name":"Paymaster Clients","description":"Publishable paymaster client CRUD (JWT)"},{"name":"Paymaster Allowlist","description":"Per-merchant contract allowlist (JWT; list also sk_*)"},{"name":"Paymaster Deny Rules","description":"Per-merchant sender and target deny rules, checked before the allowlist (JWT; list also sk_*)"},{"name":"Paymaster Spend Limits","description":"Merchant spend limits that tighten the platform limits (JWT; read also sk_*)"},{"name":"Paymaster Usage","description":"Sponsored-op usage ledger (JWT or sk_*)"},{"name":"Harness Balance","description":"Prepaid gas balance, top-ups and statements (JWT; reads also sk_*)"},{"name":"yield-deployments","description":"floYsh / Yield as a Service (YaaS). Merchant yield deployments — list, create, read, update name and branding, delete drafts, sunset and return to the active list, upload a logo, attach and remove custom domains (JWT; reads also sk_*)"},{"name":"Paymaster Activity","description":"Merchant-scoped sponsored-op feed and overview (JWT or sk_*)"}],"servers":[{"url":"https://api.dev.scx.easeflow.io","description":"Dev"}],"components":{"securitySchemes":{"sk-api-key":{"type":"http","scheme":"bearer","description":"Server-to-server secret key as `Bearer sk_*`"},"merchant-jwt":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Merchant dashboard JWT (thirdweb SIWE login)"},"paymaster-client-id":{"type":"apiKey","in":"header","name":"X-Client-Id","description":"Publishable paymaster client id (`pmc_live_*` / `pmc_test_*`)"}},"schemas":{"HealthResponseDto":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"revision":{"type":"string","example":"9f8e7d6c5b4a","description":"Short sha of the commit this build was made from, or \"unknown\"."}},"required":["status","revision"]},"LoginPayloadDto":{"type":"object","properties":{"domain":{"type":"string","example":"harness.stablecoinx.com"},"address":{"type":"string","example":"0x1234...abcd"},"statement":{"type":"string"},"uri":{"type":"string"},"version":{"type":"string","example":"1"},"chain_id":{"type":"string","example":"1"},"nonce":{"type":"string"},"issued_at":{"type":"string","format":"date-time"},"expiration_time":{"type":"string","format":"date-time"},"invalid_before":{"type":"string","format":"date-time"},"resources":{"type":"array","items":{"type":"string"}}},"required":["domain","address","version","chain_id","nonce","issued_at"]},"LoginPayloadResponseDto":{"type":"object","properties":{"payload":{"$ref":"#/components/schemas/LoginPayloadDto"}},"required":["payload"]},"VerifyRequestDto":{"type":"object","properties":{"payload":{"$ref":"#/components/schemas/LoginPayloadDto"},"signature":{"type":"string","example":"0x...","description":"0x-prefixed signature over the payload"},"email":{"type":"string","description":"Email the wallet session logged in with (thirdweb email OTP). Stored on the merchant row at creation only; existing merchants are never modified."}},"required":["payload","signature"]},"MerchantProfileDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"walletAddress":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"onboardingCompleted":{"type":"boolean"},"normalizePayoutChainId":{"type":"number","nullable":true,"description":"Normalize payout chain id; null → same chain as payment"},"normalizePayoutAddress":{"type":"string","nullable":true,"description":"Normalize payout recipient; null → merchant walletAddress"},"underpaymentToleranceBps":{"type":"number","minimum":0,"maximum":1000,"description":"Underpayment tolerance in basis points; a deposit within this margin under the invoice amount counts as paid."},"processingPaymentMode":{"type":"string","enum":["MERCHANT_ONLY","PAYER_ONLY","MERCHANT_THEN_PAYER"],"description":"Who pays the processing price of new sessions that do not override it"},"processingExpenseLimitBps":{"type":"number","minimum":0,"maximum":10000,"description":"Largest processing price the merchant pays, in basis points of the order amount; the service fee does not count toward it"},"serviceFeePayer":{"type":"string","enum":["MERCHANT","PAYER"],"description":"Who pays the service fee of new sessions that do not override it. The rate is platform-configured."}},"required":["id","walletAddress","createdAt","onboardingCompleted","underpaymentToleranceBps","processingPaymentMode","processingExpenseLimitBps","serviceFeePayer"]},"VerifyResponseDto":{"type":"object","properties":{"token":{"type":"string","description":"JWT bearer token for the merchant dashboard"},"expiresAt":{"type":"string","format":"date-time"},"merchant":{"$ref":"#/components/schemas/MerchantProfileDto"}},"required":["token","expiresAt","merchant"]},"UpdateMerchantProfileRequestDto":{"type":"object","properties":{"name":{"type":"string"},"normalizePayoutChainId":{"type":"number","nullable":true,"description":"Set/clear normalize payout chain (supported chain id, or null to reset to the payment chain)"},"normalizePayoutAddress":{"type":"string","nullable":true,"description":"Set/clear normalize payout address (EVM address, or null to reset to walletAddress)"},"underpaymentToleranceBps":{"type":"number","minimum":0,"maximum":1000,"description":"Underpayment tolerance in basis points: a deposit at least (amount - amount*bps/10000) counts as paid. 0 requires the full amount. Read live at each deposit evaluation — raising it also settles open sessions already holding a qualifying partial deposit."},"processingPaymentMode":{"type":"string","enum":["MERCHANT_ONLY","PAYER_ONLY","MERCHANT_THEN_PAYER"],"description":"Who pays the processing price of new sessions that do not override it"},"processingExpenseLimitBps":{"type":"number","minimum":0,"maximum":10000,"description":"Largest processing price the merchant pays, in basis points of the order amount (300 = 3%); applies to sessions created afterwards"},"serviceFeePayer":{"type":"string","enum":["MERCHANT","PAYER"],"description":"Who pays the service fee of new sessions that do not override it; applies to sessions created afterwards"}}},"RegisterSmartAccountRequestDto":{"type":"object","properties":{"address":{"type":"string","example":"0x9C7991b5e7ccC532Ed2dcaa70b0876ef97747992","description":"SA address derived from the merchant's in-app wallet EOA."}},"required":["address"]},"ApiKeySummaryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string"},"keyPrefix":{"type":"string","example":"sk_live_abcd","description":"Non-secret prefix of the key"},"mode":{"type":"string","enum":["live","test"],"description":"Network class the key was born with"},"lastUsedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"revokedAt":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","label","keyPrefix","createdAt"]},"ListApiKeysResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeySummaryDto"}}},"required":["items"]},"CreateApiKeyRequestDto":{"type":"object","properties":{"label":{"type":"string","example":"Backend server"},"mode":{"type":"string","enum":["live","test"],"description":"Network class of the key (`sk_live_*` / `sk_test_*`). Required and matching the selected mode at isolation activation; omission during preparation uses the deployment's environment tag."}},"required":["label"]},"CreateApiKeyResponseDto":{"type":"object","properties":{"apiKey":{"$ref":"#/components/schemas/ApiKeySummaryDto"},"rawKey":{"type":"string","description":"Full secret key — shown ONCE at creation","example":"sk_live_..."}},"required":["apiKey","rawKey"]},"RevokeApiKeyResponseDto":{"type":"object","properties":{"apiKey":{"$ref":"#/components/schemas/ApiKeySummaryDto"}},"required":["apiKey"]},"DeliveredAssetDto":{"type":"object","properties":{"symbol":{"type":"string","example":"USDC"},"tokenAddress":{"type":"string","nullable":true,"description":"Token contract on the delivery chain; null when not recorded"},"decimals":{"type":"number","example":6},"amount":{"type":"string","description":"Raw on-chain integer amount in the asset's decimals","example":"49990000"}},"required":["symbol","decimals","amount"]},"ChainAmountReceivedDto":{"type":"object","properties":{"chainId":{"type":"number"},"amountReceived":{"type":"string","description":"Decimal string"},"currency":{"type":"string","example":"usd"}},"required":["chainId","amountReceived","currency"]},"ServiceFeeSummaryDto":{"type":"object","properties":{"rateBps":{"type":"number","nullable":true,"description":"Fee rate snapshotted at creation; null when the session has no fee terms"},"payer":{"type":"string","enum":["MERCHANT","PAYER",null],"nullable":true},"calculatedAmount":{"type":"string","nullable":true,"description":"Fee calculated from the order at creation (decimal string). Terms, not money in hand."},"collectedAmount":{"type":"string","nullable":true,"description":"Fee actually retained at settlement (decimal string); null until a settlement record exists, and can be lower than the calculation after a tolerance-accepted underpayment"},"status":{"type":"string","enum":["exempt","waived","pending","earned"],"description":"exempt = no fee terms; waived = a zero calculated fee (0% rate, or a tiny order floored to zero); earned = settlement after confirmed delivery, where an accepted underpayment can leave the collected amount at zero; pending otherwise"}},"required":["rateBps","payer","calculatedAmount","collectedAmount","status"]},"MerchantPaymentOptionDto":{"type":"object","properties":{"id":{"type":"string"},"symbol":{"type":"string"},"chainId":{"type":"number"},"networkName":{"type":"string"},"amountDue":{"type":"string","description":"Amount the payer sends with this option (decimal string)"},"processingPrice":{"type":"string","nullable":true,"description":"Processing price in the option's token (decimal string)"},"processingPayer":{"type":"string","enum":["MERCHANT","PAYER",null],"nullable":true},"quoteExpiresAt":{"type":"string","nullable":true,"format":"date-time"},"exclusion":{"type":"string","enum":["price_unavailable","exceeds_expense_limit",null],"nullable":true,"description":"Why the option was not offered to the payer as priced"},"unavailableReason":{"type":"string","enum":["price_unavailable","quote_expired",null],"nullable":true}},"required":["id","symbol","chainId","networkName","amountDue","processingPrice","processingPayer","quoteExpiresAt","exclusion","unavailableReason"]},"PaymentSettlementSummaryDto":{"type":"object","properties":{"currency":{"type":"string","example":"usd"},"processingPayer":{"type":"string","enum":["MERCHANT","PAYER",null],"nullable":true},"quotedProcessing":{"type":"string","description":"Accepted processing price (decimal string)"},"processingCollected":{"type":"string","description":"Processing amount retained at settlement (decimal string)"},"serviceFee":{"type":"string","description":"Service fee retained at settlement (decimal string)"},"merchantProceeds":{"type":"string","description":"Amount paid to the merchant for the order (decimal string)"},"merchantExcess":{"type":"string","description":"Additional amount paid to the merchant, such as overpayment (decimal string)"}},"required":["currency","processingPayer","quotedProcessing","processingCollected","serviceFee","merchantProceeds","merchantExcess"]},"MerchantSessionSummaryDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test"]},"id":{"type":"string","format":"uuid"},"amount":{"type":"string","description":"Decimal string"},"amountDue":{"type":"string","description":"Amount the payer owes: the order amount plus the accepted option's payer-paid processing price (decimal string)"},"currency":{"type":"string","example":"usd"},"status":{"type":"string","enum":["settling","pending","awaiting_payment","partial","confirming","bridging","completed","failed","expired","cancelled"]},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"paidAt":{"type":"string","nullable":true,"format":"date-time"},"txHash":{"type":"string","nullable":true},"bridgeTxHash":{"type":"string","nullable":true},"bridgeChainId":{"type":"number","nullable":true},"lzGuid":{"type":"string","nullable":true,"description":"LayerZero V2 message guid"},"payoutChainId":{"type":"number","nullable":true,"description":"Effective LI.FI cross-chain payout target chain id (null unless LI.FI normalize)"},"sandboxMode":{"type":"boolean"},"tokenReceived":{"type":"string","nullable":true,"description":"Symbol label of the settled asset: \"sUSDe\", \"USDe\", input symbols joined with \"+\", or the token a cross-chain bridge reported delivering instead of USDe. An unverified bridge delivery keeps the requested asset; deliveredAssets holds what was measured. Null until settlement is sent."},"usdeAmount":{"type":"string","nullable":true,"description":"Raw 18-decimal USDe amount delivered/swapped. Null for forward settlements and for cross-chain deliveries in a token other than USDe."},"sUsdeAmount":{"type":"string","nullable":true,"description":"Raw 18-decimal sUSDe shares minted. Set only for stake settlements."},"deliveredChainId":{"type":"number","nullable":true,"description":"Chain id where the settled asset landed. Null until completed."},"deliveredAssets":{"description":"What landed on deliveredChainId once completed: one entry per asset, raw on-chain amounts in the asset's decimals. Empty until completed, and when a cross-chain bridge delivery could not be verified as USDe.","type":"array","items":{"$ref":"#/components/schemas/DeliveredAssetDto"}},"deliveredTxHash":{"type":"string","nullable":true,"description":"Transaction that delivered the settled funds to the recipient, on deliveredChainId (or on payoutChainId when a cross-chain delivery in another token leaves deliveredChainId null). Null until completed; a cross-chain delivery staked through the composer may carry none."},"failureReason":{"type":"string","nullable":true,"description":"Reason the session failed (decoded revert, bridge failure, or a support note after manual recovery). Null unless failed."},"failedByOperatorAt":{"type":"string","nullable":true,"format":"date-time","description":"Set when StablecoinX support closed the session after recovering its funds manually. Null unless failed."},"amountReceived":{"type":"string","nullable":true,"description":"Amount observed on the leading payment chain as a decimal string."},"amountOverpaid":{"type":"string","nullable":true,"description":"Amount received above the invoice amount. Null when not overpaid."},"amountReceivedChainId":{"type":"number","nullable":true},"amountReceivedByChain":{"type":"array","items":{"$ref":"#/components/schemas/ChainAmountReceivedDto"}},"expiredWithFundsAt":{"type":"string","nullable":true,"format":"date-time"},"cancelledAt":{"type":"string","nullable":true,"format":"date-time"},"cancelledWithFundsAt":{"type":"string","nullable":true,"format":"date-time"},"metadata":{"type":"object","nullable":true,"additionalProperties":{"type":"string"},"description":"Metadata map the merchant set at creation. Null when none was set."},"processingPaymentMode":{"type":"string","enum":["MERCHANT_ONLY","PAYER_ONLY","MERCHANT_THEN_PAYER",null],"nullable":true,"description":"Processing payment mode resolved at creation; null for sessions created without processing prices"},"processingExpenseLimitBps":{"type":"number","nullable":true},"processingPayer":{"type":"string","enum":["MERCHANT","PAYER",null],"nullable":true,"description":"Processing payer fixed when the first payment arrived"},"serviceFee":{"description":"Service-fee terms and accounting for this session","allOf":[{"$ref":"#/components/schemas/ServiceFeeSummaryDto"}]},"paymentOptions":{"description":"Every option priced at creation, including those not offered to the payer and why","type":"array","items":{"$ref":"#/components/schemas/MerchantPaymentOptionDto"}},"settlementRecord":{"description":"Settlement amounts; null until the payout settles","anyOf":[{"$ref":"#/components/schemas/PaymentSettlementSummaryDto"},{"type":"object","nullable":true,"enum":[null]}]}},"required":["id","amount","amountDue","currency","status","expiresAt","createdAt","sandboxMode","deliveredAssets","amountReceivedByChain","cancelledAt","cancelledWithFundsAt","metadata","processingPaymentMode","processingExpenseLimitBps","processingPayer","serviceFee","paymentOptions","settlementRecord"]},"ListMerchantSessionsResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MerchantSessionSummaryDto"}},"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"}},"required":["items","total","page","limit"]},"LineItemDto":{"type":"object","properties":{"name":{"type":"string","example":"Pro plan (annual)"},"quantity":{"type":"number","example":1},"unitPrice":{"type":"string","example":"100.00","description":"Decimal string"},"total":{"type":"string","example":"100.00","description":"Decimal string"}},"required":["name","quantity","unitPrice","total"]},"CreateSessionRequestDto":{"type":"object","properties":{"amount":{"type":"string","example":"100.00","description":"Total amount as a positive decimal string"},"merchantName":{"type":"string","example":"Acme Inc."},"lineItems":{"type":"array","items":{"$ref":"#/components/schemas/LineItemDto"}},"paymentOptionSymbols":{"type":"array","description":"Restrict offered payment currencies; defaults to all supported","items":{"type":"string","enum":["USDe","USDT","USDC"]}},"expiresInSec":{"type":"number","example":3600,"description":"Session lifetime in seconds (60..604800)"},"successUrl":{"type":"string","example":"https://shop.example.com/order/123/success","description":"Absolute https URL the payer is redirected to after settlement"},"sandboxMode":{"type":"boolean","description":"Compatibility flag during preparation: true selects testnets, false mainnets. Ignored when mode isolation is enabled; the credential/header selects the mode."},"payoutChainId":{"type":"number","nullable":true,"description":"Per-session normalize payout chain override (supported chain id)"},"payoutAddress":{"type":"string","nullable":true,"description":"Per-session normalize payout address override (EVM address)"},"stakingOverride":{"type":"string","nullable":true,"enum":["DEFAULT","STAKE","NORMALIZE","NO_STAKE",null],"default":"DEFAULT","description":"Per-session override of the merchant staking policy; DEFAULT or null inherits it"},"processingPaymentMode":{"type":"string","enum":["MERCHANT_ONLY","PAYER_ONLY","MERCHANT_THEN_PAYER"],"description":"Who pays each payment option's processing price for this session: MERCHANT_ONLY offers only options within the merchant's processing expense limit, PAYER_ONLY adds the price to the payer's amount, MERCHANT_THEN_PAYER lets the merchant pay within the limit and the payer above it. Omit to use the merchant's account setting."},"serviceFeePayer":{"type":"string","enum":["MERCHANT","PAYER"],"description":"Who pays this session's service fee: PAYER adds it to every option's amountDue, MERCHANT withholds it from the proceeds. Omit to use the merchant's account setting."},"metadata":{"type":"object","nullable":true,"maxProperties":20,"additionalProperties":{"type":"string","maxLength":500},"example":{"orderId":"order_8421","customerId":"cus_123"},"description":"Your correlation data, e.g. your order id under \"orderId\". Flat map of string values: up to 20 keys of 1-40 characters (A-Z, a-z, 0-9, \"_\", \".\", \"-\"; \"__proto__\", \"constructor\" and \"prototype\" are reserved), values up to 500 characters without control characters. Key order is not preserved. Returned on merchant session reads and in every webhook event; never shown to the payer or returned by the public session endpoints. Do not put secrets or personal data here."}},"required":["amount"]},"CreateSessionResponseDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test"]},"id":{"type":"string","format":"uuid"},"paymentUrl":{"type":"string","example":"https://pay.stablecoinx.com/session/<id>"},"status":{"type":"string","enum":["settling","pending","awaiting_payment","partial","confirming","bridging","completed","failed","expired","cancelled"]},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","paymentUrl","status","expiresAt","createdAt"]},"CancelSessionResponseDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test"]},"id":{"type":"string"},"status":{"type":"string","enum":["cancelled"]},"cancelledAt":{"type":"string","format":"date-time"}},"required":["id","status","cancelledAt"]},"RetryAcceptedResponseDto":{"type":"object","properties":{"ok":{"type":"boolean","example":true}},"required":["ok"]},"NetworkDto":{"type":"object","properties":{"name":{"type":"string","example":"Base Sepolia"},"chainId":{"type":"number","example":84532},"standard":{"type":"string","example":"ERC-20"}},"required":["name","chainId","standard"]},"PaymentOptionProcessingDto":{"type":"object","properties":{"price":{"type":"string","example":"0.42","description":"Processing price in the option's token (decimal string)"},"payer":{"type":"string","enum":["MERCHANT","PAYER"],"description":"Who pays the processing price"},"quoteExpiresAt":{"type":"string","format":"date-time","description":"The price is not valid as payment instructions after this time"}},"required":["price","payer","quoteExpiresAt"]},"PaymentOptionDto":{"type":"object","properties":{"id":{"type":"string"},"symbol":{"type":"string","enum":["USDe","USDT","USDC"]},"tokenAddress":{"type":"string"},"decimals":{"type":"number","example":6},"network":{"$ref":"#/components/schemas/NetworkDto"},"depositAddress":{"type":"string","description":"CREATE2-predicted Forwarder address the payer sends funds to"},"amountDue":{"type":"string","example":"100.42","description":"Amount the payer sends with this option: the order amount plus a payer-paid processing price and a payer-paid service fee (decimal string)"},"available":{"type":"boolean","description":"False when the option has no current processing price; it must not be used as payment instructions"},"unavailableReason":{"type":"string","enum":["price_unavailable","quote_expired",null],"nullable":true},"processing":{"description":"Null for sessions created without a processing price","anyOf":[{"$ref":"#/components/schemas/PaymentOptionProcessingDto"},{"type":"object","nullable":true,"enum":[null]}]}},"required":["id","symbol","tokenAddress","decimals","network","depositAddress","amountDue","available","unavailableReason","processing"]},"SessionServiceFeeDto":{"type":"object","properties":{"amount":{"type":"string","example":"1.00","description":"Service fee in the session currency (decimal string)"},"payer":{"type":"string","enum":["MERCHANT","PAYER"],"description":"Who pays the service fee"}},"required":["amount","payer"]},"SessionDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test"]},"id":{"type":"string","format":"uuid"},"merchantName":{"type":"string"},"amount":{"type":"string","description":"Decimal string"},"currency":{"type":"string","example":"usd"},"status":{"type":"string","enum":["settling","pending","awaiting_payment","partial","confirming","bridging","completed","failed","expired","cancelled"]},"paymentOptions":{"type":"array","items":{"$ref":"#/components/schemas/PaymentOptionDto"}},"lineItems":{"type":"array","items":{"$ref":"#/components/schemas/LineItemDto"}},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"paidAt":{"type":"string","format":"date-time"},"txHash":{"type":"string","nullable":true},"sandboxMode":{"type":"boolean"},"serviceFee":{"description":"Service-fee terms fixed at creation, uniform across options; null when the session has no fee terms. A PAYER fee is already included in every option's amountDue.","anyOf":[{"$ref":"#/components/schemas/SessionServiceFeeDto"},{"type":"object","nullable":true,"enum":[null]}]},"successUrl":{"type":"string"}},"required":["id","merchantName","amount","currency","status","paymentOptions","lineItems","expiresAt","createdAt","sandboxMode","serviceFee"]},"SessionStatusResponseDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test"]},"status":{"type":"string","enum":["settling","pending","awaiting_payment","partial","confirming","bridging","completed","failed","expired","cancelled"]},"webhookDelivered":{"type":"boolean","description":"True when the user-ui is clear to redirect the payer to successUrl"},"currency":{"type":"string","example":"usd","description":"Lowercase ISO 4217 currency code for the session amount fields"},"amountReceived":{"type":"string","nullable":true,"description":"Amount received on the accepted option's chain for a partial payment, otherwise on the chain with the largest balance. Decimal string; null until a deposit lands."},"amountRemaining":{"type":"string","nullable":true,"description":"Amount still owed on amountReceivedChainId under the accepted processing terms, clamped at \"0\". Always \"0\" once the session settled as paid (a tolerance-accepted shortfall is not owed). Null until a deposit lands."},"amountReceivedChainId":{"type":"number","nullable":true},"amountReceivedByChain":{"type":"array","items":{"$ref":"#/components/schemas/ChainAmountReceivedDto"}},"acceptedPaymentOptionId":{"type":"string","nullable":true,"description":"ID of the payment option (`paymentOptions[].id`) whose processing terms the first deposit fixed. The rest of a partial payment is owed under these terms in this option's token, so `amountRemaining` includes its payer-paid processing price. Null until a deposit lands."},"paymentReceivedAt":{"type":"string","format":"date-time","nullable":true,"description":"When the sufficient source deposit reached its 14-confirmation gate (payment received). Null while the deposit is unconfirmed, and again while a reorg or a recheck that could not read the chain reopens the gate before source execution; it is then set with the new release time."}},"required":["status","webhookDelivered","currency","amountReceived","amountRemaining","amountReceivedByChain","acceptedPaymentOptionId","paymentReceivedAt"]},"CreateWebhookEndpointRequestDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test"],"description":"Routing mode; inherited from the selected credential/header at isolation activation"},"url":{"type":"string","example":"https://shop.example.com/webhooks/scx"},"events":{"example":["session.confirming"],"type":"array","items":{"type":"string"}},"description":{"type":"string"},"apiVersion":{"type":"string","nullable":true,"enum":["2026-10-02",null],"description":"null = latest"}},"required":["url"]},"WebhookEndpointSummaryDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test",null],"nullable":true,"description":"null means routing mode has not been assigned"},"id":{"type":"string","format":"uuid"},"url":{"type":"string","example":"https://shop.example.com/webhooks/scx"},"events":{"example":["session.confirming"],"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"description":{"type":"string","nullable":true},"apiVersion":{"type":"string","nullable":true,"example":"2026-10-02","description":"Pinned contract version; null follows latest"},"secretPrefix":{"type":"string","example":"whsec_abcd","description":"Non-secret prefix of the signing secret"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","url","events","enabled","apiVersion","secretPrefix","createdAt"]},"CreateWebhookEndpointResponseDto":{"type":"object","properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpointSummaryDto"},"rawSecret":{"type":"string","description":"Signing secret — shown ONCE at creation","example":"whsec_..."}},"required":["endpoint","rawSecret"]},"ListWebhookEndpointsResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpointSummaryDto"}}},"required":["items"]},"UpdateWebhookEndpointRequestDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test"],"description":"Assign an unclassified endpoint; an assigned mode is immutable"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"description":{"type":"string"},"apiVersion":{"type":"string","nullable":true,"enum":["2026-10-02",null],"description":"null = latest"}}},"RotateWebhookSecretResponseDto":{"type":"object","properties":{"rawSecret":{"type":"string","description":"New signing secret — shown ONCE","example":"whsec_..."}},"required":["rawSecret"]},"WebhookDeliverySummaryDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test",null],"nullable":true,"description":"null means routing mode has not been assigned"},"id":{"type":"string","format":"uuid"},"eventType":{"type":"string"},"webhookEventId":{"type":"string"},"sessionId":{"type":"string","format":"uuid","nullable":true},"exhaustedAt":{"type":"string","nullable":true,"format":"date-time"},"manual":{"type":"boolean"},"endpointUrl":{"type":"string"},"status":{"type":"string","enum":["pending","dispatching","success","failed","cancelled"]},"httpStatus":{"type":"number","nullable":true},"errorMessage":{"type":"string","nullable":true},"scheduledAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","eventType","webhookEventId","sessionId","exhaustedAt","manual","endpointUrl","status","scheduledAt","createdAt"]},"ListWebhookDeliveriesResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliverySummaryDto"}},"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"}},"required":["items","total","page","limit"]},"WebhookDeliveryDetailDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test",null],"nullable":true,"description":"null means routing mode has not been assigned"},"id":{"type":"string","format":"uuid"},"eventType":{"type":"string"},"webhookEventId":{"type":"string"},"sessionId":{"type":"string","format":"uuid","nullable":true},"exhaustedAt":{"type":"string","nullable":true,"format":"date-time"},"manual":{"type":"boolean"},"endpointUrl":{"type":"string"},"status":{"type":"string","enum":["pending","dispatching","success","failed","cancelled"]},"httpStatus":{"type":"number","nullable":true},"errorMessage":{"type":"string","nullable":true},"scheduledAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","nullable":true,"format":"date-time"},"payload":{"oneOf":[{"type":"object","required":["id","type","createdAt","data"],"properties":{"id":{"type":"string"},"mode":{"type":"string","enum":["test","live"],"description":"Absent on events retained before mode stamping"},"apiVersion":{"type":"string","description":"Absent on retained legacy session events"},"type":{"type":"string","enum":["session.confirming","session.partial","session.completed","session.expired","session.cancelled","session.payment_detected","session.failed"]},"createdAt":{"type":"string","format":"date-time"},"data":{"type":"object","required":["session"],"properties":{"session":{"type":"object","required":["id","merchantName","amount","currency","status","expiresAt","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"mode":{"type":"string","enum":["test","live"]},"merchantName":{"type":"string"},"amount":{"type":"string"},"currency":{"type":"string"},"status":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"cancelledAt":{"type":"string","format":"date-time"},"paidAt":{"type":"string","format":"date-time"},"txHash":{"type":"string"},"amountReceived":{"type":"string"},"amountPaid":{"type":"string"},"amountRemaining":{"type":"string"},"failureReason":{"type":"string"},"amountReceivedChainId":{"type":"number"},"amountReceivedByChain":{"type":"array","items":{"type":"object","required":["chainId","amountReceived","currency"],"properties":{"chainId":{"type":"number"},"amountReceived":{"type":"string"},"currency":{"type":"string"}}}},"tokenReceived":{"type":"string"},"usdeAmount":{"type":"string"},"sUsdeAmount":{"type":"string"},"deliveredChainId":{"type":"number"},"deliveredAssets":{"type":"array","items":{"type":"object","required":["symbol","tokenAddress","decimals","amount"],"properties":{"symbol":{"type":"string"},"tokenAddress":{"type":"string","nullable":true},"decimals":{"type":"number"},"amount":{"type":"string"}}}},"deliveredTxHash":{"type":"string"},"payoutChainId":{"type":"number"},"payoutAddress":{"type":"string"},"amountOverpaid":{"type":"string"},"metadata":{"type":"object","additionalProperties":{"type":"string"}}}}}}}},{"type":"object","required":["id","apiVersion","type","createdAt","data"],"properties":{"id":{"type":"string"},"mode":{"type":"string","enum":["test","live",null],"nullable":true,"description":"null until the balance ledger is assigned a routing mode; absent on retained events"},"apiVersion":{"type":"string"},"type":{"type":"string","enum":["balance.low","balance.exhausted"]},"createdAt":{"type":"string","format":"date-time"},"data":{"type":"object","required":["balance"],"properties":{"balance":{"type":"object","required":["balanceUsd"],"properties":{"balanceUsd":{"type":"number"},"burnRatePerDayUsd":{"type":"number"},"daysLeft":{"type":"number"}}}}}}}],"description":"Original event payload retained for replay"},"responseBody":{"type":"string","nullable":true}},"required":["id","eventType","webhookEventId","sessionId","exhaustedAt","manual","endpointUrl","status","scheduledAt","createdAt","payload","responseBody"]},"WebhookRetryAcceptedResponseDto":{"type":"object","properties":{"ok":{"type":"boolean","example":true}},"required":["ok"]},"SessionWebhookEventDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test",null],"nullable":true},"id":{"type":"string","example":"evt_3f0c…"},"type":{"type":"string","example":"session.confirming"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","type","createdAt"]},"NextAutomaticWebhookAttemptDto":{"type":"object","properties":{"scheduledAt":{"type":"string","format":"date-time"},"attempt":{"type":"number","example":4,"description":"1-based number of the scheduled automatic attempt; manual resends are not counted"},"maxAttempts":{"type":"number","example":11}},"required":["scheduledAt","attempt","maxAttempts"]},"SessionWebhookEndpointStatusDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test",null],"nullable":true},"endpointId":{"type":"string","format":"uuid"},"endpointUrl":{"type":"string"},"delivered":{"type":"boolean","description":"A delivery of the event to this endpoint succeeded"},"exhausted":{"type":"boolean","description":"Automatic delivery stopped without an acknowledgement"},"resendInProgress":{"type":"boolean","description":"A manual resend to this endpoint is pending or dispatching"},"nextAutomaticAttempt":{"description":"The automatic attempt that is scheduled or in flight; `null` once delivered or when none is","anyOf":[{"$ref":"#/components/schemas/NextAutomaticWebhookAttemptDto"},{"type":"object","nullable":true,"enum":[null]}]}},"required":["endpointId","endpointUrl","delivered","exhausted","resendInProgress","nextAutomaticAttempt"]},"SessionWebhookStatusDto":{"type":"object","properties":{"event":{"description":"The session's latest webhook event — the one a manual resend sends; among events with the same timestamp, prefer an enabled endpoint's subscribed type, then descending event id. `null` if none exists yet","anyOf":[{"$ref":"#/components/schemas/SessionWebhookEventDto"},{"type":"object","nullable":true,"enum":[null]}]},"resendableEndpointCount":{"type":"number","description":"Enabled endpoints subscribed to the event type — the ones a manual resend reaches"},"endpoints":{"description":"Endpoints that have at least one delivery of the event","type":"array","items":{"$ref":"#/components/schemas/SessionWebhookEndpointStatusDto"}}},"required":["event","resendableEndpointCount","endpoints"]},"PaymasterClientSummaryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string"},"clientId":{"type":"string","example":"pmc_live_abcd","description":"Publishable client id — safe to ship in frontend bundles"},"mode":{"type":"string","enum":["live","test",null],"nullable":true,"description":"Network class: live keys sponsor mainnets, test keys testnets; null for a malformed stored id"},"allowedOrigins":{"example":["https://dapp.example.com"],"type":"array","items":{"type":"string"}},"allowedChainIds":{"example":[8453,42161],"type":"array","items":{"type":"number"}},"gasMode":{"type":"string","enum":["sponsored","user_paid","both"],"description":"Which gas modes this key's users get: merchant-sponsored, user-paid-in-stables, or both"},"lastUsedAt":{"type":"string","nullable":true,"format":"date-time"},"revokedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","label","clientId","allowedOrigins","allowedChainIds","gasMode","createdAt"]},"ListPaymasterClientsResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PaymasterClientSummaryDto"}}},"required":["items"]},"CreatePaymasterClientRequestDto":{"type":"object","properties":{"label":{"type":"string"},"mode":{"type":"string","enum":["live","test"],"description":"Required and matching the selected mode at isolation activation; defaults to live during preparation"},"allowedOrigins":{"type":"array","items":{"type":"string"}},"allowedChainIds":{"type":"array","items":{"type":"number"}},"gasMode":{"type":"string","enum":["sponsored","user_paid","both"],"default":"sponsored"}},"required":["label","allowedOrigins","allowedChainIds"]},"CreatePaymasterClientResponseDto":{"type":"object","properties":{"client":{"$ref":"#/components/schemas/PaymasterClientSummaryDto"}},"required":["client"]},"UpdatePaymasterClientRequestDto":{"type":"object","properties":{"label":{"type":"string"},"allowedOrigins":{"type":"array","items":{"type":"string"}},"allowedChainIds":{"type":"array","items":{"type":"number"}},"gasMode":{"type":"string","enum":["sponsored","user_paid","both"]}}},"ContractAllowlistEntryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"chainId":{"type":"number","example":8453},"contractAddress":{"type":"string","example":"0x1234...abcd"},"label":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}},"required":["id","chainId","contractAddress","createdAt"]},"ListContractAllowlistResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ContractAllowlistEntryDto"}}},"required":["items"]},"CreateContractAllowlistRequestDto":{"type":"object","properties":{"chainId":{"type":"number","example":8453},"contractAddress":{"type":"string","example":"0x1234...abcd"},"label":{"type":"string"}},"required":["chainId","contractAddress"]},"SpendLimitValuesDto":{"type":"object","properties":{"perTxCapUsdMicros":{"type":"string","nullable":true,"example":"5000000","description":"Applies to billed sponsored operations. Test cost estimates never debit the monetary balance."},"perUserDailyCapUsdMicros":{"type":"string","nullable":true,"example":"25000000","description":"The merchant's value bounds sponsored ops only; the platform's value applies to every op."},"perUserRatePerHour":{"type":"number","nullable":true,"example":10}},"required":["perTxCapUsdMicros","perUserDailyCapUsdMicros","perUserRatePerHour"]},"SpendLimitsResponseDto":{"type":"object","properties":{"mode":{"type":"string","enum":["live","test"],"description":"Selected network mode after isolation activation; omitted for shared preparation limits"},"platform":{"$ref":"#/components/schemas/SpendLimitValuesDto"},"merchant":{"$ref":"#/components/schemas/SpendLimitValuesDto"},"effective":{"$ref":"#/components/schemas/SpendLimitValuesDto"}},"required":["platform","merchant","effective"]},"UpdateSpendLimitsRequestDto":{"type":"object","properties":{"perTxCapUsdMicros":{"type":"string","nullable":true,"example":"5000000","description":"Applies to billed sponsored operations. Test cost estimates never debit the monetary balance."},"perUserDailyCapUsdMicros":{"type":"string","nullable":true,"example":"25000000","description":"The merchant's value bounds sponsored ops only; the platform's value applies to every op."},"perUserRatePerHour":{"type":"number","nullable":true,"example":10}}},"DenyRuleEntryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"chainId":{"type":"number","example":8453},"kind":{"type":"string","enum":["sender","target"]},"address":{"type":"string","example":"0x1234...abcd"},"label":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}},"required":["id","chainId","kind","address","createdAt"]},"ListDenyRulesResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/DenyRuleEntryDto"}},"total":{"type":"number","description":"Total rules for the merchant; items may be capped below this"}},"required":["items","total"]},"CreateDenyRuleRequestDto":{"type":"object","properties":{"chainId":{"type":"number","example":8453},"kind":{"type":"string","enum":["sender","target"]},"address":{"type":"string","example":"0x1234...abcd"},"label":{"type":"string"}},"required":["chainId","kind","address"]},"JsonRpcRequestDto":{"type":"object","properties":{"jsonrpc":{"type":"string","example":"2.0","enum":["2.0"]},"id":{"description":"Request id echoed back in the response; null or missing is rejected with -32700","oneOf":[{"type":"number"},{"type":"string"}],"example":1},"method":{"type":"string","enum":["pm_sponsorUserOperation","pm_getPaymasterStubData","pm_getPaymasterData"],"example":"pm_sponsorUserOperation"},"params":{"type":"array","items":{},"description":"[userOp, entryPoint, chainId, context?] for every method — chainId as `0x` hex, decimal string or number; context is optional `{token}` for user-paid gas.","example":[{"sender":"0x…","nonce":"0x0","callData":"0xb61d27f6…"},"0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108","0x14a34"]}},"required":["jsonrpc","id","method","params"]},"JsonRpcResponseDto":{"type":"object","properties":{"jsonrpc":{"type":"string","example":"2.0"},"id":{"oneOf":[{"type":"number"},{"type":"string","nullable":true}],"example":1},"result":{"type":"object","description":"Present on success — method-specific result object","additionalProperties":true},"error":{"type":"object","description":"Present on error","properties":{"code":{"type":"number","example":-32601},"message":{"type":"string","example":"Unknown method: eth_chainId"}}}},"required":["jsonrpc","id"]},"BundlerJsonRpcRequestDto":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"],"example":"2.0"},"id":{"oneOf":[{"type":"number"},{"type":"string"}],"example":1},"method":{"type":"string","description":"ERC-4337 bundler method, forwarded unchanged; only `eth_sendUserOperation` is gated by sponsorship policy","example":"eth_sendUserOperation"},"params":{"type":"array","items":{},"description":"Method parameters as the bundler expects them, e.g. `[userOp, entryPoint]` for `eth_sendUserOperation`; omitted for parameterless methods such as `thirdweb_getUserOperationGasPrice`","example":[{"sender":"0x…","nonce":"0x0","callData":"0xb61d27f6…"},"0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"]}},"required":["jsonrpc","id","method"]},"UsageEntryDto":{"type":"object","properties":{"networkMode":{"type":"string","enum":["live","test",null],"nullable":true,"description":"Recorded chain network class; null for an unknown chain"},"gasMode":{"type":"string","enum":["sponsored","user_paid"]},"id":{"type":"string","format":"uuid"},"clientId":{"type":"string"},"chainId":{"type":"number"},"sender":{"type":"string"},"target":{"type":"string","description":"First call target; see `targets` for a batched operation"},"targets":{"description":"Every call target in execution order; empty when no call was decoded (refused before decoding or unsupported callData)","type":"array","items":{"type":"string"}},"origin":{"type":"string","nullable":true},"userOpHash":{"type":"string","nullable":true},"status":{"type":"string","enum":["denied_target","denied_upstream","denied_billing_balance","denied_merchant_limit","denied_gas_mode","denied_chain","denied_entrypoint","denied_origin","denied_malformed","denied_rate_limit","denied_spend_cap","denied_global_cap","denied_price_unavailable","submitted","onchain_success","onchain_reverted","dropped","denied_merchant_rule"]},"mode":{"type":"string","enum":["sponsored","user_paid"],"deprecated":true,"description":"Gas payment mode; use gasMode. sponsored — merchant-billed gas; user_paid — the user paid gas in an ERC-20 pulled in the same operation"},"token":{"type":"string","nullable":true,"description":"ERC-20 the user paid gas with (user_paid rows only)"},"reason":{"type":"string","nullable":true},"txHash":{"type":"string","nullable":true},"blockNumber":{"type":"string","nullable":true,"description":"Decimal string"},"actualGasCost":{"type":"string","nullable":true,"description":"wei, decimal string"},"actualGasUsed":{"type":"string","nullable":true,"description":"gas units, decimal string"},"ethUsdPriceMicros":{"type":"string","nullable":true,"description":"microdollars (× 10^6)"},"actualGasCostUsdMicros":{"type":"string","nullable":true,"description":"microdollars (× 10^6)"},"marginUsdMicros":{"type":"string","nullable":true,"description":"Platform exchange margin realised on a user_paid op: token paid minus raw gas USD, microdollars (× 10^6)"},"finalizedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","clientId","chainId","sender","target","targets","status","mode","createdAt"]},"ListUsageResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/UsageEntryDto"}},"nextCursor":{"type":"string","nullable":true,"description":"Opaque cursor for the next page"}},"required":["items"]},"MerchantPaymasterOverviewTotalsDto":{"type":"object","properties":{"totalOps":{"type":"string"},"successCount":{"type":"string"},"revertCount":{"type":"string"},"totalGasCostWei":{"type":"string"},"totalGasCostEth":{"type":"string"},"windowOps":{"type":"string"},"windowGasCostWei":{"type":"string"},"windowGasCostEth":{"type":"string"},"sponsoredOps":{"type":"string","description":"Attempts signed by the paymaster, settled or not"},"deniedOps":{"type":"string","description":"Attempts refused before signing"},"windowSponsoredOps":{"type":"string"},"windowDeniedOps":{"type":"string"}},"required":["totalOps","successCount","revertCount","totalGasCostWei","totalGasCostEth","windowOps","windowGasCostWei","windowGasCostEth","sponsoredOps","deniedOps","windowSponsoredOps","windowDeniedOps"]},"MerchantPaymasterChainStatsDto":{"type":"object","properties":{"chainId":{"type":"number"},"isTestnet":{"type":"boolean","description":"Test-network operation; informational cost estimates never debit a balance"},"totalOps":{"type":"string"},"totalGasCostWei":{"type":"string"},"totalGasCostEth":{"type":"string"},"windowOps":{"type":"string"},"windowGasCostWei":{"type":"string"},"windowGasCostEth":{"type":"string"},"sponsoredOps":{"type":"string"},"deniedOps":{"type":"string"}},"required":["chainId","isTestnet","totalOps","totalGasCostWei","totalGasCostEth","windowOps","windowGasCostWei","windowGasCostEth","sponsoredOps","deniedOps"]},"MerchantPaymasterOverviewResponseDto":{"type":"object","properties":{"window":{"type":"string","enum":["24h","7d","30d","all"]},"generatedAt":{"type":"string","format":"date-time"},"totals":{"$ref":"#/components/schemas/MerchantPaymasterOverviewTotalsDto"},"chains":{"type":"array","items":{"$ref":"#/components/schemas/MerchantPaymasterChainStatsDto"}}},"required":["window","generatedAt","totals","chains"]},"MerchantPaymasterRecentOpDto":{"type":"object","properties":{"chainId":{"type":"number"},"version":{"type":"string","example":"v0.8"},"txHash":{"type":"string"},"logIndex":{"type":"number"},"blockNumber":{"type":"string","description":"Decimal string"},"blockTimestamp":{"type":"string","format":"date-time"},"sender":{"type":"string"},"success":{"type":"boolean"},"gasCostWei":{"type":"string"},"gasCostEth":{"type":"string"}},"required":["chainId","version","txHash","logIndex","blockNumber","blockTimestamp","sender","success","gasCostWei","gasCostEth"]},"MerchantActivityEntryDto":{"type":"object","properties":{"networkMode":{"type":"string","enum":["live","test",null],"nullable":true,"description":"Recorded chain network class; null for an unknown chain"},"gasMode":{"type":"string","enum":["sponsored","user_paid",null],"nullable":true},"source":{"type":"string","enum":["onchain","prechain"],"description":"onchain — a settled UserOperationEvent; prechain — an attempt that never reached chain"},"status":{"type":"string","enum":["denied_target","denied_upstream","denied_billing_balance","denied_merchant_limit","denied_gas_mode","denied_chain","denied_entrypoint","denied_origin","denied_malformed","denied_rate_limit","denied_spend_cap","denied_global_cap","denied_price_unavailable","submitted","onchain_success","onchain_reverted","dropped","denied_merchant_rule"]},"chainId":{"type":"number"},"version":{"type":"string","nullable":true,"example":"v0.8","description":"EntryPoint version; null for prechain rows"},"sender":{"type":"string"},"userOpHash":{"type":"string","nullable":true},"txHash":{"type":"string","nullable":true},"blockTimestamp":{"type":"string","nullable":true,"format":"date-time"},"success":{"type":"boolean","nullable":true},"gasCostWei":{"type":"string","nullable":true,"description":"wei, decimal string"},"gasCostEth":{"type":"string","nullable":true},"clientId":{"type":"string","nullable":true},"target":{"type":"string","nullable":true,"description":"First call target; see `targets` for a batched operation"},"targets":{"nullable":true,"description":"Every call target in execution order; null exactly where `target` is","type":"array","items":{"type":"string"}},"origin":{"type":"string","nullable":true},"reason":{"type":"string","nullable":true,"description":"Denial reason for prechain rows"},"actualGasCostUsdMicros":{"type":"string","nullable":true,"description":"microdollars (× 10^6)"},"mode":{"type":"string","nullable":true,"enum":["sponsored","user_paid",null],"deprecated":true,"description":"Gas payment mode; use gasMode"},"token":{"type":"string","nullable":true,"description":"ERC-20 the user paid gas with (user_paid rows only)"},"timestamp":{"type":"string","format":"date-time","description":"blockTimestamp for onchain rows, createdAt for prechain rows; pass it back as `cursor`"}},"required":["source","status","chainId","version","sender","userOpHash","txHash","blockTimestamp","success","gasCostWei","gasCostEth","clientId","target","targets","origin","reason","actualGasCostUsdMicros","mode","token","timestamp"]},"ListMerchantActivityResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MerchantActivityEntryDto"}},"nextCursor":{"type":"string","nullable":true,"format":"date-time","description":"Cursor for the next page; null on the last page"}},"required":["items","nextCursor"]}}}}