{"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","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]}}}}},"tags":["Merchant"],"security":[{"merchant-jwt":[]}]},"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","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","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":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListApiKeysResponseDto"}}}},"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":["Merchant"],"security":[{"merchant-jwt":[]}]},"post":{"operationId":"MerchantController_createApiKey","summary":"Create an API key","description":"Returns the raw secret key once — store it securely.","parameters":[],"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","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"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeApiKeyResponseDto"}}}},"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":["Merchant"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/sessions":{"get":{"operationId":"MerchantController_listSessions","summary":"List merchant sessions","parameters":[{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}},{"name":"status","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMerchantSessionsResponseDto"}}}},"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":["Merchant"],"security":[{"merchant-jwt":[]}]},"post":{"operationId":"MerchantController_createSession","summary":"Create a session from the dashboard","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionResponseDto"}}}},"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":["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"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantSessionSummaryDto"}}}},"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":["Merchant"],"security":[{"merchant-jwt":[]}]}},"/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"}}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryAcceptedResponseDto"}}}},"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":["Merchant"],"security":[{"merchant-jwt":[]}]}},"/v1/sessions/{id}":{"get":{"operationId":"SessionController_getSession","summary":"Get a payment session","description":"Public — returns the session with payment options and line items.","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":{"post":{"operationId":"SessionController_create","summary":"Create a payment session","description":"Server-to-server — requires an `sk_*` secret key in the Authorization header.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionResponseDto"}}}},"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":["Sessions"],"security":[{"sk-api-key":[]}]}},"/v1/merchants/me/webhooks":{"post":{"operationId":"WebhookController_create","summary":"Create a webhook endpoint (JWT)","parameters":[],"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":[],"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":"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":"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":"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":"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":"id","required":true,"in":"path","description":"Webhook endpoint id (UUID)","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}},{"name":"status","required":false,"in":"query","schema":{}}],"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/sessions/{id}/retry-webhook":{"post":{"operationId":"WebhookRetryController_retryWebhook","summary":"Retry webhook delivery for a session (JWT)","parameters":[{"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","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/webhooks":{"post":{"operationId":"WebhookApiController_create","summary":"Create a webhook endpoint (sk_*)","parameters":[],"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":[],"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":"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":"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":"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":"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/sessions/{id}/retry-webhook":{"post":{"operationId":"WebhookApiRetryController_retryWebhook","summary":"Retry webhook delivery for a session (sk_*)","parameters":[{"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"]}}}}},"tags":["Webhooks"],"security":[{"sk-api-key":[]}]}},"/v1/paymaster/clients":{"get":{"operationId":"PaymasterClientsController_list","summary":"List paymaster clients","parameters":[],"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":[],"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":"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":"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":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListContractAllowlistResponseDto"}}}},"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 Allowlist"],"security":[{"merchant-jwt":[]}]},"post":{"operationId":"ContractAllowlistController_upsert","summary":"Add or update an allowlisted contract","parameters":[],"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","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":"id","required":true,"in":"path","description":"Allowlist entry id","schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"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 Allowlist"],"security":[{"merchant-jwt":[]}]}},"/v1/paymaster/limits":{"get":{"operationId":"SpendLimitsController_get","summary":"Current sponsorship limits: platform, merchant, effective","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpendLimitsResponseDto"}}}},"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 Spend Limits"],"security":[{"merchant-jwt":[]}]},"patch":{"operationId":"SpendLimitsController_update","summary":"Tighten sponsorship limits (null clears a limit back to the platform default)","parameters":[],"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","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":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDenyRulesResponseDto"}}}},"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 Deny Rules"],"security":[{"merchant-jwt":[]}]},"post":{"operationId":"DenyRuleController_upsert","summary":"Add or update a deny rule","parameters":[],"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","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":"id","required":true,"in":"path","description":"Deny rule id","schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"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 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 or v0.7; `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.\n- `pm_sponsorUserOperation` — the same signed result for merchant-sponsored gas; a `context.token` is refused.\n\nThe result of every method is `{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, both on EntryPoint v0.7) 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 neither EntryPoint v0.8 nor v0.7 |\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","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Object"}}}},"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":"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":"mode","required":false,"in":"query","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","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":[]}]}},"/v1/merchants/me/paymaster/overview":{"get":{"operationId":"MerchantOverviewController_get","summary":"Merchant-scoped paymaster overview","parameters":[{"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"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantPaymasterOverviewResponseDto"}}}},"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 Activity"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/paymaster/overview/recent-ops":{"get":{"operationId":"MerchantOverviewController_recent","summary":"Merchant's recent sponsored ops","parameters":[{"name":"limit","required":false,"in":"query","description":"1–100, default 20","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","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":[]}]}},"/v1/merchants/me/paymaster/activity":{"get":{"operationId":"MerchantActivityController_list","summary":"Unified merchant paymaster activity (cursor-paginated)","parameters":[{"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":"mode","required":false,"in":"query","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","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":[]}]}},"/v1/merchants/me/balance":{"get":{"operationId":"MerchantBalanceController_summary","summary":"Billing summary: prepaid balance, markup, current period","parameters":[],"responses":{"200":{"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":["Harness Balance"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/balance/charges":{"get":{"operationId":"MerchantBalanceController_charges","summary":"Gas charges (cursor-paginated, newest first)","parameters":[{"name":"limit","required":false,"in":"query","schema":{}},{"name":"cursor","required":false,"in":"query","schema":{}},{"name":"chainId","required":false,"in":"query","schema":{}}],"responses":{"200":{"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":["Harness Balance"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/balance/charges.csv":{"get":{"operationId":"MerchantBalanceController_chargesCsv","summary":"Charge history as CSV over a UTC date range, oldest first","parameters":[{"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"}}],"responses":{"200":{"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":["Harness Balance"],"security":[{"merchant-jwt":[]}]}},"/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":"month","required":true,"in":"query","description":"UTC calendar month, YYYY-MM","schema":{"type":"string"}}],"responses":{"200":{"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":["Harness Balance"],"security":[{"merchant-jwt":[]}]}},"/v1/merchants/me/balance/topups":{"get":{"operationId":"MerchantBalanceController_listTopUps","summary":"Balance top-ups, newest first","parameters":[],"responses":{"200":{"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":["Harness Balance"],"security":[{"merchant-jwt":[]}]},"post":{"operationId":"MerchantBalanceController_createTopUp","summary":"Create a self-serve top-up payment session","parameters":[],"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":["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":[],"responses":{"200":{"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":[]}]}},"/v1/merchants/me/yield-deployments/contract-sets":{"get":{"operationId":"YieldDeploymentController_contractSets","summary":"List deployed contract sets belonging to the merchant on a network","parameters":[],"responses":{"200":{"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":[]}]}},"/v1/merchants/me/yield-deployments/{id}/contracts":{"post":{"operationId":"YieldDeploymentController_linkContracts","summary":"Link an existing contract set to an unconfigured draft","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"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":[]}]}},"/v1/merchants/me/yield-deployments":{"get":{"operationId":"YieldDeploymentController_list","summary":"List the merchant's yield deployments","parameters":[],"responses":{"200":{"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":[]}]},"post":{"operationId":"YieldDeploymentController_create","summary":"Create a yield deployment","parameters":[],"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":[]}]}},"/v1/merchants/me/yield-deployments/{id}":{"get":{"operationId":"YieldDeploymentController_findOne","summary":"Get a yield deployment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"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":[]}]},"patch":{"operationId":"YieldDeploymentController_update","summary":"Update a yield deployment's name or branding","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"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":[]}]},"delete":{"operationId":"YieldDeploymentController_remove","summary":"Delete a draft yield deployment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"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":[]}]}},"/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":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"202":{"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":[]}]}},"/v1/merchants/me/yield-deployments/{id}/sunset":{"post":{"operationId":"YieldDeploymentController_sunset","summary":"Retire a yield deployment from the merchant's active list","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"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":[]}]},"delete":{"operationId":"YieldDeploymentController_unsunset","summary":"Return a sunset yield deployment to the active list","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"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":[]}]}},"/v1/merchants/me/yield-deployments/{id}/domains":{"post":{"operationId":"YieldDeploymentController_addDomain","summary":"Attach a custom domain to a yield deployment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"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":[]}]}},"/v1/merchants/me/yield-deployments/{id}/domains/{domainId}":{"delete":{"operationId":"YieldDeploymentController_removeDomain","summary":"Remove a custom domain from a yield deployment","parameters":[{"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","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":"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. Server-to-server endpoints authenticate with an `sk_*` secret key; the merchant dashboard uses a SIWE-issued JWT; the paymaster RPC proxy uses a publishable `pmc_*` client id in the `X-Client-Id` header.\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.harness.stablecoinx.com/) — 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.harness.stablecoinx.com/llms-full.txt) — product overview and navigation, including how to find a deployment's public site.\n- [Merchant OpenAPI](https://api.harness.stablecoinx.com/docs#/yield-deployments) ([JSON](https://api.harness.stablecoinx.com/docs/openapi.json)) — configuration routes under `/v1/merchants/me/yield-deployments`, authenticated with a merchant JWT. 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 dashboard — profile, API keys, sessions, webhooks (JWT)"},{"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)"},{"name":"Paymaster Deny Rules","description":"Per-merchant sender and target deny rules, checked before the allowlist (JWT)"},{"name":"Paymaster Spend Limits","description":"Merchant spend limits that tighten the platform limits (JWT)"},{"name":"Paymaster Usage","description":"Sponsored-op usage ledger (JWT)"},{"name":"Harness Balance","description":"Prepaid gas balance, top-ups and statements (JWT)"},{"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)"},{"name":"Paymaster Activity","description":"Merchant-scoped sponsored-op feed and overview (JWT)"}],"servers":[{"url":"https://api.harness.stablecoinx.com","description":"Production"}],"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":"object","nullable":true},"name":{"type":"object","nullable":true},"createdAt":{"type":"string","format":"date-time"},"onboardingCompleted":{"type":"boolean"},"normalizePayoutChainId":{"type":"object","nullable":true,"description":"SCX-276: normalize payout chain id; null → same chain as payment"},"normalizePayoutAddress":{"type":"object","nullable":true,"description":"SCX-276: 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."}},"required":["id","walletAddress","createdAt","onboardingCompleted","underpaymentToleranceBps"]},"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":"object","nullable":true,"description":"SCX-276: set/clear normalize payout chain (supported chain id, or null to reset to the payment chain)"},"normalizePayoutAddress":{"type":"object","nullable":true,"description":"SCX-276: 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."}}},"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"},"scopes":{"type":"array","items":{"type":"string"}},"lastUsedAt":{"type":"object","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"revokedAt":{"type":"object","nullable":true,"format":"date-time"}},"required":["id","label","keyPrefix","scopes","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"}},"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"]},"ChainAmountReceivedDto":{"type":"object","properties":{"chainId":{"type":"number"},"amountReceived":{"type":"string","description":"Decimal string"},"currency":{"type":"string","example":"usd"}},"required":["chainId","amountReceived","currency"]},"MerchantSessionSummaryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"amount":{"type":"string","description":"Decimal string"},"currency":{"type":"string","example":"usd"},"status":{"type":"string","enum":["pending","awaiting_payment","partial","confirming","bridging","completed","failed","expired"]},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"paidAt":{"type":"object","nullable":true,"format":"date-time"},"txHash":{"type":"object","nullable":true},"bridgeTxHash":{"type":"object","nullable":true},"bridgeChainId":{"type":"object","nullable":true},"lzGuid":{"type":"object","nullable":true,"description":"LayerZero V2 message guid"},"payoutChainId":{"type":"object","nullable":true,"description":"Effective LI.FI cross-chain payout target chain id (null unless LI.FI normalize)"},"sandboxMode":{"type":"boolean"},"tokenReceived":{"type":"object","nullable":true,"description":"Symbol label of what the merchant received once settled: \"sUSDe\", \"USDe\", or input symbols joined with \"+\". Null until completed."},"usdeAmount":{"type":"object","nullable":true,"description":"Raw 18-decimal USDe amount delivered/swapped. Null for forward settlements."},"sUsdeAmount":{"type":"object","nullable":true,"description":"Raw 18-decimal sUSDe shares minted. Set only for stake settlements."},"failureReason":{"type":"object","nullable":true,"description":"Reason the session failed (decoded revert / bridge / retry). Null unless failed."},"amountReceived":{"type":"object","nullable":true,"description":"Amount observed on the leading payment chain as a decimal string."},"amountOverpaid":{"type":"object","nullable":true,"description":"Amount received above the invoice amount. Null when not overpaid."},"amountReceivedChainId":{"type":"object","nullable":true},"amountReceivedByChain":{"type":"array","items":{"$ref":"#/components/schemas/ChainAmountReceivedDto"}},"expiredWithFundsAt":{"type":"object","nullable":true,"format":"date-time"}},"required":["id","amount","currency","status","expiresAt","createdAt","sandboxMode","amountReceivedByChain"]},"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":"When true, only testnet payment options are attached; when false, only mainnet. Omit to use the API default."},"payoutChainId":{"type":"object","nullable":true,"description":"SCX-276: per-session normalize payout chain override (supported chain id)"},"payoutAddress":{"type":"object","nullable":true,"description":"SCX-276: per-session normalize payout address override (EVM address)"}},"required":["amount"]},"CreateSessionResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"paymentUrl":{"type":"string","example":"https://pay.stablecoinx.com/session/<id>"},"status":{"type":"string","enum":["pending","awaiting_payment","partial","confirming","bridging","completed","failed","expired"]},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","paymentUrl","status","expiresAt","createdAt"]},"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"]},"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"}},"required":["id","symbol","tokenAddress","decimals","network","depositAddress"]},"SessionDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"merchantName":{"type":"string"},"amount":{"type":"string","description":"Decimal string"},"currency":{"type":"string","example":"usd"},"status":{"type":"string","enum":["pending","awaiting_payment","partial","confirming","bridging","completed","failed","expired"]},"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"},"successUrl":{"type":"string"}},"required":["id","merchantName","amount","currency","status","paymentOptions","lineItems","expiresAt","createdAt","sandboxMode"]},"SessionStatusResponseDto":{"type":"object","properties":{"status":{"type":"string","enum":["pending","awaiting_payment","partial","confirming","bridging","completed","failed","expired"]},"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":"object","nullable":true,"description":"Amount received on the leading payment chain as a decimal string. Null until a deposit lands."},"amountRemaining":{"type":"object","nullable":true,"description":"Amount still owed on the leading payment chain, 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":"object","nullable":true},"amountReceivedByChain":{"type":"array","items":{"$ref":"#/components/schemas/ChainAmountReceivedDto"}}},"required":["status","webhookDelivered","currency","amountReceived","amountRemaining","amountReceivedByChain"]},"CreateWebhookEndpointRequestDto":{"type":"object","properties":{"url":{"type":"string","example":"https://shop.example.com/webhooks/scx"},"events":{"example":["session.confirming"],"type":"array","items":{"type":"string"}},"description":{"type":"string"}},"required":["url"]},"WebhookEndpointSummaryDto":{"type":"object","properties":{"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":"object","nullable":true},"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","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":{"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"description":{"type":"string"}}},"RotateWebhookSecretResponseDto":{"type":"object","properties":{"rawSecret":{"type":"string","description":"New signing secret — shown ONCE","example":"whsec_..."}},"required":["rawSecret"]},"WebhookDeliverySummaryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"eventType":{"type":"string"},"sessionId":{"type":"string","format":"uuid"},"endpointUrl":{"type":"string"},"status":{"type":"string","enum":["pending","dispatching","success","failed","cancelled"]},"httpStatus":{"type":"object","nullable":true},"errorMessage":{"type":"object","nullable":true},"scheduledAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":"object","nullable":true,"format":"date-time"}},"required":["id","eventType","sessionId","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"]},"WebhookRetryAcceptedResponseDto":{"type":"object","properties":{"ok":{"type":"boolean","example":true}},"required":["ok"]},"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"],"description":"Network class: live keys sponsor mainnets, test keys testnets"},"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":"object","nullable":true,"format":"date-time"},"revokedAt":{"type":"object","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","label","clientId","mode","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"],"default":"live"},"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":"object","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":"object","nullable":true,"example":"5000000","description":"Applies to billed sponsored ops only: a live key on a billed chain."},"perUserDailyCapUsdMicros":{"type":"object","nullable":true,"example":"25000000","description":"The merchant's value bounds sponsored ops only; the platform's value applies to every op."},"perUserRatePerHour":{"type":"object","nullable":true,"example":10}},"required":["perTxCapUsdMicros","perUserDailyCapUsdMicros","perUserRatePerHour"]},"SpendLimitsResponseDto":{"type":"object","properties":{"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":"object","nullable":true,"example":"5000000","description":"Applies to billed sponsored ops only: a live key on a billed chain."},"perUserDailyCapUsdMicros":{"type":"object","nullable":true,"example":"25000000","description":"The merchant's value bounds sponsored ops only; the platform's value applies to every op."},"perUserRatePerHour":{"type":"object","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":"object","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":{"type":"object","nullable":true,"example":1},"result":{"type":"object","description":"Present on success — method-specific result object"},"error":{"type":"object","description":"Present on error","properties":{"code":{"type":"number","example":-32601},"message":{"type":"string","example":"Unknown method: eth_chainId"}}}},"required":["jsonrpc","id"]},"Object":{"type":"object","properties":{}},"UsageEntryDto":{"type":"object","properties":{"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":"object","nullable":true},"userOpHash":{"type":"object","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"],"description":"sponsored — merchant-billed gas; user_paid — the user paid gas in an ERC-20 pulled in the same operation"},"token":{"type":"object","nullable":true,"description":"ERC-20 the user paid gas with (user_paid rows only)"},"reason":{"type":"object","nullable":true},"txHash":{"type":"object","nullable":true},"blockNumber":{"type":"object","nullable":true,"description":"Decimal string"},"actualGasCost":{"type":"object","nullable":true,"description":"wei, decimal string"},"actualGasUsed":{"type":"object","nullable":true,"description":"gas units, decimal string"},"ethUsdPriceMicros":{"type":"object","nullable":true,"description":"microdollars (× 10^6)"},"actualGasCostUsdMicros":{"type":"object","nullable":true,"description":"microdollars (× 10^6)"},"marginUsdMicros":{"type":"object","nullable":true,"description":"Platform exchange margin realised on a user_paid op: token paid minus raw gas USD, microdollars (× 10^6)"},"finalizedAt":{"type":"object","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":"object","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":"Testnet gas is metered but never billed"},"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":{"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]},"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"]}}}}