openapi: 3.2.0 info: title: Parlay Billing API description: Real-time sports odds aggregation from **33 books and data sources** updated every 2-120 seconds depending on source cadence. version: 3.2.0 x-credit-currency: credits x-credit-cost-catalogue-url: /v1/meta/credit-costs x-pricing-url: /v1/pricing x-usage-url: /v1/usage contact: name: ParlayAPI support url: https://parlay-api.com/support email: support@parlay-api.com license: name: ParlayAPI Terms of Service url: https://parlay-api.com/terms termsOfService: https://parlay-api.com/terms servers: - url: https://parlay-api.com description: Production (primary; HTTP/2, TLS 1.3). - url: https://api.parlay-api.com description: Production (high-volume; bypasses Cloudflare edge for trading bots above 30 req/min). Same origin, same auth, same endpoints. tags: - name: Billing paths: /billing/checkout: post: tags: - Billing summary: Create Checkout description: Create a Stripe Checkout Session. Returns checkout URL. operationId: create_checkout_billing_checkout_post parameters: - name: tier in: query required: true schema: type: string title: Tier - name: promo in: query required: false schema: anyOf: - type: string - type: 'null' title: Promo responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /billing/portal: post: tags: - Billing summary: Create Portal description: Create Stripe Customer Portal session for self-service management. operationId: create_portal_billing_portal_post responses: '200': description: Successful Response content: application/json: schema: {} get: tags: - Billing summary: Open Portal Via Token description: 'Durable billing-portal entry point (the emailed / dashboard link). `token` is a long-lived, single-purpose, customer-scoped opaque handle (billing.get_or_create_portal_token). It is NOT a login or session token: it can ONLY open this one customer''s Stripe billing portal (change / cancel plan, update card, view invoices). Because it never authenticates the user into their account and grants no API access, a long TTL is acceptable here in a way it is not for password-reset or magic-login links. It remains revocable and customer-scoped. On every visit we mint a FRESH Stripe portal session server-side and 302 into it, so this link never goes stale even though the underlying Stripe session URL expires within minutes.' operationId: open_portal_via_token_billing_portal_get parameters: - name: token in: query required: false schema: type: string default: '' title: Token responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /billing/subscription/cancel: post: tags: - Billing summary: Cancel Subscription Route description: 'Cancel the caller''s subscription, self-serve. Deliberately NOT named /billing/cancel: that path is already the Checkout-abandoned landing page, and one word meaning two opposite things is how a customer ends up on the wrong one. The mode is chosen from the subscription''s own status rather than asked of the customer, because only one answer is ever right: active / trialing -> cancel at period end. They paid for this period, they keep it, the key drops to Free when it runs out. past_due / unpaid / incomplete -> cancel now. There is no paid period left to keep, and at_period_end would leave Stripe retrying the failed payment, which is the thing ticket #271 asked us to stop. An immediate cancel files a support ticket for the open invoice. We do not void it here on purpose: that is a money decision.' operationId: cancel_subscription_route_billing_subscription_cancel_post responses: '200': description: Successful Response content: application/json: schema: {} /billing/portal/send-link: post: tags: - Billing summary: Admin Send Portal Link description: 'Admin-only: email a customer a DURABLE billing-management link. This is the sanctioned replacement for pasting a raw Stripe portal session URL into a support reply (which expires in minutes). Give it either the account `email` or a `customer_id`.' operationId: admin_send_portal_link_billing_portal_send_link_post parameters: - name: email in: query required: false schema: anyOf: - type: string - type: 'null' title: Email - name: customer_id in: query required: false schema: anyOf: - type: string - type: 'null' title: Customer Id responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /billing/portal/revoke: post: tags: - Billing summary: Admin Revoke Portal Link description: 'Admin-only: revoke a customer''s durable portal token. Any link already emailed stops working immediately.' operationId: admin_revoke_portal_link_billing_portal_revoke_post parameters: - name: email in: query required: false schema: anyOf: - type: string - type: 'null' title: Email - name: customer_id in: query required: false schema: anyOf: - type: string - type: 'null' title: Customer Id responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /billing/success: get: tags: - Billing summary: Checkout Success operationId: checkout_success_billing_success_get parameters: - name: session_id in: query required: false schema: type: string default: '' title: Session Id responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /billing/success-page: get: tags: - Billing summary: Checkout Success Page Alias operationId: checkout_success_page_alias_billing_success_page_get parameters: - name: session_id in: query required: false schema: type: string default: '' title: Session Id responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /billing/cancel: get: tags: - Billing summary: Checkout Cancel operationId: checkout_cancel_billing_cancel_get responses: '200': description: Successful Response content: application/json: schema: {} /billing/cancel-page: get: tags: - Billing summary: Checkout Cancel Page Alias operationId: checkout_cancel_page_alias_billing_cancel_page_get responses: '200': description: Successful Response content: application/json: schema: {} components: schemas: HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type input: title: Input ctx: type: object title: Context type: object required: - loc - msg - type title: ValidationError securitySchemes: apiKeyHeader: type: apiKey in: header name: X-API-Key description: API key passed in the X-API-Key header. Recommended. apiKeyQuery: type: apiKey in: query name: apiKey description: API key passed as the ?apiKey= query parameter. Useful for browser fetch() and webhooks where header control is limited. Equivalent to X-API-Key. bearerAuth: type: http scheme: bearer bearerFormat: APIKey description: 'API key passed via Authorization: Bearer . Equivalent to X-API-Key for compatibility with auth libraries that expect bearer tokens.'