Wispr AI Payments API

The Payments API from Wispr AI — 22 operation(s) for payments.

OpenAPI Specification

wispr-ai-payments-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: Wispr Backend Analytics Payments API
  description: Wispr Backend API
  version: 0.5.2
tags:
- name: Payments
paths:
  /api/v1/payment/enterprise/switch-plan:
    post:
      tags:
      - Payments
      summary: Switch Enterprise Plan
      description: 'Switch an enterprise subscription to a new plan.


        This endpoint:

        1. Validates the user is an admin

        2. Validates the new plan is valid and different from current

        3. Updates the subscription in Stripe

        4. Updates the database record

        5. Returns the updated subscription details'
      operationId: switch_enterprise_plan
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SwitchPlanRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
      - ApiKeyHeaderPatched: []
  /api/v1/payment/support/switch-plan:
    post:
      tags:
      - Payments
      summary: Switch Support Plan
      operationId: switch_support_plan
      security:
      - APIKeyHeader: []
      parameters:
      - name: email
        in: query
        required: true
        schema:
          type: string
          description: The email of the user to switch the plan for
          title: Email
        description: The email of the user to switch the plan for
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SwitchPlanRequest'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/switch-plan:
    post:
      tags:
      - Payments
      summary: Switch Plan
      operationId: switch_plan
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SwitchPlanRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
      - ApiKeyHeaderPatched: []
  /api/v1/payment/create_enterprise_checkout_session:
    post:
      tags:
      - Payments
      summary: Create Enterprise Checkout Session
      description: 'Create an enterprise Stripe Checkout session.


        Optional GA4 params for attribution tracking.'
      operationId: create_enterprise_checkout_session
      security:
      - ApiKeyHeaderPatched: []
      parameters:
      - name: currency
        in: query
        required: false
        schema:
          $ref: '#/components/schemas/Currency'
          description: 'Deprecated: ignored for pricing. The checkout currency is resolved server-side from the caller''s IP (WP-7177). Retained only for backwards compatibility with existing clients.'
          deprecated: true
          default: usd
        description: 'Deprecated: ignored for pricing. The checkout currency is resolved server-side from the caller''s IP (WP-7177). Retained only for backwards compatibility with existing clients.'
        deprecated: true
      - name: ga4_client_id
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: GA4 client_id for attribution tracking
          title: Ga4 Client Id
        description: GA4 client_id for attribution tracking
      - name: platform
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: Platform for attribution tracking
          title: Platform
        description: Platform for attribution tracking
      - name: fbp
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: Meta _fbp cookie value
          title: Fbp
        description: Meta _fbp cookie value
      - name: fbc
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: Meta _fbc click ID cookie value
          title: Fbc
        description: Meta _fbc click ID cookie value
      - name: utm_source
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: UTM source parameter
          title: Utm Source
        description: UTM source parameter
      - name: utm_medium
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: UTM medium parameter
          title: Utm Medium
        description: UTM medium parameter
      - name: utm_campaign
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: UTM campaign parameter
          title: Utm Campaign
        description: UTM campaign parameter
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateEnterpriseCheckoutRequest'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/create-checkout-session:
    post:
      tags:
      - Payments
      summary: Create Checkout Session
      description: Create a Stripe Checkout session.
      operationId: create_checkout_session
      security:
      - ApiKeyHeaderPatched: []
      parameters:
      - name: plan
        in: query
        required: true
        schema:
          $ref: '#/components/schemas/StripeProductOption'
      - name: custom_redirect
        in: query
        required: false
        schema:
          type: boolean
          default: false
          title: Custom Redirect
      - name: promo_code
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Promo Code
      - name: currency
        in: query
        required: false
        schema:
          type: string
          default: usd
          title: Currency
      - name: variant
        in: query
        required: false
        schema:
          anyOf:
          - type: string
            maxLength: 64
            pattern: ^[a-zA-Z0-9_-]+$
          - type: 'null'
          description: Optional pricing-experiment variant claim. Re-validated server-side against the registry; invalid or stale claims fall back to canonical pricing.
          title: Variant
        description: Optional pricing-experiment variant claim. Re-validated server-side against the registry; invalid or stale claims fall back to canonical pricing.
      - name: ga4_client_id
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: GA4 client_id for attribution tracking
          title: Ga4 Client Id
        description: GA4 client_id for attribution tracking
      - name: platform
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: Platform for attribution tracking
          title: Platform
        description: Platform for attribution tracking
      - name: fbp
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: Meta _fbp cookie value
          title: Fbp
        description: Meta _fbp cookie value
      - name: fbc
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: Meta _fbc click ID cookie value
          title: Fbc
        description: Meta _fbc click ID cookie value
      - name: utm_source
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: UTM source parameter
          title: Utm Source
        description: UTM source parameter
      - name: utm_medium
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: UTM medium parameter
          title: Utm Medium
        description: UTM medium parameter
      - name: utm_campaign
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: UTM campaign parameter
          title: Utm Campaign
        description: UTM campaign parameter
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/create-bank-transfer-invoice:
    post:
      tags:
      - Payments
      summary: Create Bank Transfer Invoice
      operationId: create_bank_transfer_invoice
      security:
      - ApiKeyHeaderPatched: []
      parameters:
      - name: plan
        in: query
        required: true
        schema:
          $ref: '#/components/schemas/StripeProductOption'
      - name: currency
        in: query
        required: false
        schema:
          type: string
          default: usd
          title: Currency
      - name: country
        in: query
        required: false
        schema:
          $ref: '#/components/schemas/EUCountry'
          default: NL
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/success:
    get:
      tags:
      - Payments
      summary: Success
      description: Handle a successful payment.
      operationId: success
      parameters:
      - name: session_id
        in: query
        required: true
        schema:
          type: string
          title: Session Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/cancel:
    get:
      tags:
      - Payments
      summary: Cancel
      description: 'Handle a cancelled Stripe checkout. Stripe always substitutes

        ``{CHECKOUT_SESSION_ID}`` in the registered cancel_url before redirecting,

        so a legitimate hit always carries a ``session_id``. Declaring it required

        lets FastAPI 422 bot/crawler traffic at the boundary (no Stripe call, no

        template render) and closes the log-amplification vector on this

        unauthenticated endpoint. Value-level garbage (``undefined``, ``null``,

        unreplaced ``{CHECKOUT_SESSION_ID}`` literals) is filtered in the service.

        No bearer tokens are accepted here — the Stripe session_id is the

        capability token.'
      operationId: cancel
      parameters:
      - name: session_id
        in: query
        required: true
        schema:
          type: string
          title: Session Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/error:
    get:
      tags:
      - Payments
      summary: Error
      description: Handle a successful payment.
      operationId: error
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /api/v1/payment/webhook:
    post:
      tags:
      - Payments
      summary: Webhook Received
      description: Handle a Stripe webhook.
      operationId: webhook_received
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /api/v1/payment/metadata-webhook:
    post:
      tags:
      - Payments
      summary: Metadata Webhook Received
      description: Handle a Stripe webhook.
      operationId: metadata_webhook_received
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /api/v1/payment/revenuecat/webhook:
    post:
      tags:
      - Payments
      summary: Revenuecat Webhook Received
      description: Handle a RevenueCat webhook.
      operationId: revenuecat_webhook_received
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /api/v1/payment/customer-portal:
    get:
      tags:
      - Payments
      summary: Customer Portal
      description: Redirect to the customer portal.
      operationId: customer_portal
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
      security:
      - ApiKeyHeaderPatched: []
  /api/v1/payment/enterprise-portal:
    get:
      tags:
      - Payments
      summary: Enterprise Portal
      description: Redirect to the customer portal.
      operationId: enterprise_portal
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
      security:
      - ApiKeyHeaderPatched: []
  /api/v1/payment/subscription:
    delete:
      tags:
      - Payments
      summary: Cancel Subscription
      operationId: cancel_subscription
      security:
      - ApiKeyHeaderPatched: []
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
    get:
      tags:
      - Payments
      summary: Get Subscription Details
      operationId: get_subscription_details
      security:
      - ApiKeyHeaderPatched: []
      parameters:
      - name: device_id
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          description: The device ID of the user
          title: Device Id
        description: The device ID of the user
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/subscription-watch/start:
    post:
      tags:
      - Payments
      summary: Subscription Watch Start
      description: Start (or atomically replace) a billing subscription invalidation watch session.
      operationId: subscription_watch_start
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionWatchStartResponse'
      security:
      - ApiKeyHeaderPatched: []
  /api/v1/payment/subscription-watch/stream:
    get:
      tags:
      - Payments
      summary: Subscription Watch Stream
      description: SSE stream of ``subscription_changed`` invalidations for billing UI (20m TTL).
      operationId: subscription_watch_stream
      security:
      - ApiKeyHeaderPatched: []
      parameters:
      - name: X-Billing-Watch-Token
        in: header
        required: true
        schema:
          type: string
          title: X-Billing-Watch-Token
      responses:
        '200':
          description: Successful Response
          content:
            text/event-stream:
              schema:
                type: string
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/create-promotion-code:
    post:
      tags:
      - Payments
      summary: Create Promotion Code
      operationId: create_promotion_code
      security:
      - APIKeyHeader: []
      parameters:
      - name: coupon_code
        in: query
        required: true
        schema:
          type: string
          title: Coupon Code
      - name: email
        in: query
        required: true
        schema:
          type: string
          title: Email
      - name: expires_in_days
        in: query
        required: false
        schema:
          type: integer
          default: 30
          title: Expires In Days
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/pricing/by-ip:
    get:
      tags:
      - Payments
      summary: Pricing By Ip
      description: Return location-aware pricing for the caller's IP (or provided IP override).
      operationId: pricing_by_ip
      parameters:
      - name: variant
        in: query
        required: false
        schema:
          anyOf:
          - type: string
            maxLength: 64
            pattern: ^[a-zA-Z0-9_-]+$
          - type: 'null'
          description: Optional pricing-experiment variant claim. Returns variant-specific price IDs for the resolved currency; invalid or stale claims fall back to canonical pricing.
          title: Variant
        description: Optional pricing-experiment variant claim. Returns variant-specific price IDs for the resolved currency; invalid or stale claims fall back to canonical pricing.
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PricingByIpResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/pricing/by-currency:
    get:
      tags:
      - Payments
      summary: Pricing By Currency
      description: 'Return the catalog pricing grid for an explicit currency, without an IP lookup.


        Powers the current-plan billing card, which prices in the subscription''s own currency

        rather than the caller''s geo-IP currency. Public catalog pricing only — no user data.'
      operationId: pricing_by_currency
      parameters:
      - name: currency
        in: query
        required: true
        schema:
          $ref: '#/components/schemas/Currency'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrencyPricingResponse'
        '404':
          description: No pricing available for the requested currency
        '429':
          description: Too Many Requests
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/currency/by-country-code:
    get:
      tags:
      - Payments
      summary: Get Currency By Country Code
      description: Return the currency for a given country code.
      operationId: get_currency_by_country_code
      parameters:
      - name: country_code
        in: query
        required: true
        schema:
          type: string
          title: Country Code
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /api/v1/payment/migrate-subscription:
    post:
      tags:
      - Payments
      summary: Migrate Subscription
      description: "Migrate the current user's subscription (personal or enterprise) to a new currency.\n\n- If the user belongs to an enterprise (has `enterprise_id`), attempt to migrate\n  the enterprise subscription.\n- Otherwise, migrate the user's personal subscription."
      operationId: migrate_subscription
      security:
      - APIKeyHeader: []
      parameters:
      - name: target_currency
        in: query
        required: true
        schema:
          $ref: '#/components/schemas/Currency'
      - name: user_id
        in: query
        required: true
        schema:
          type: string
          format: uuid
          title: User Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    CurrencyPricingResponse:
      properties:
        currency:
          type: string
          title: Currency
        FLOW_PRO_MONTHLY:
          $ref: '#/components/schemas/ProductPricingResponse'
        FLOW_PRO_YEARLY:
          $ref: '#/components/schemas/ProductPricingResponse'
        FLOW_STUDENT_MONTHLY:
          $ref: '#/components/schemas/ProductPricingResponse'
        FLOW_STUDENT_YEARLY:
          $ref: '#/components/schemas/ProductPricingResponse'
        FLOW_BUSINESS_MONTHLY:
          $ref: '#/components/schemas/ProductPricingResponse'
        FLOW_BUSINESS_YEARLY:
          $ref: '#/components/schemas/ProductPricingResponse'
      type: object
      required:
      - currency
      - FLOW_PRO_MONTHLY
      - FLOW_PRO_YEARLY
      - FLOW_STUDENT_MONTHLY
      - FLOW_STUDENT_YEARLY
      - FLOW_BUSINESS_MONTHLY
      - FLOW_BUSINESS_YEARLY
      title: CurrencyPricingResponse
      description: Pricing for all Flow products in a single currency.
    EUCountry:
      type: string
      enum:
      - NL
      - DE
      - FR
      - BE
      - ES
      - IE
      title: EUCountry
    IPLocation:
      properties:
        ip:
          anyOf:
          - type: string
          - type: 'null'
          title: Ip
        country_code:
          anyOf:
          - type: string
          - type: 'null'
          title: Country Code
        country_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Country Name
      type: object
      title: IPLocation
      description: Geographic location resolved from an IP address.
    CreateEnterpriseCheckoutRequest:
      properties:
        plan:
          $ref: '#/components/schemas/StripeProductOption'
        seats:
          type: integer
          title: Seats
        add_billing_info:
          type: boolean
          title: Add Billing Info
          default: false
      type: object
      required:
      - plan
      - seats
      title: CreateEnterpriseCheckoutRequest
    StripeProductOption:
      type: string
      enum:
      - FLOW_PRO_MONTHLY
      - FLOW_PRO_YEARLY
      - FLOW_STUDENT_MONTHLY
      - FLOW_STUDENT_YEARLY
      - FLOW_TEAM_MONTHLY
      - FLOW_TEAM_YEARLY
      - FLOW_BUSINESS_MONTHLY
      - FLOW_BUSINESS_YEARLY
      title: StripeProductOption
    SubscriptionWatchStartResponse:
      properties:
        watch_token:
          type: string
          title: Watch Token
          description: Opaque token; send as ``X-Billing-Watch-Token`` on the SSE stream.
        expires_at:
          type: string
          format: date-time
          title: Expires At
          description: UTC wall-clock time when the watch session ends.
      type: object
      required:
      - watch_token
      - expires_at
      title: Subscription watch start response
      description: Response from ``POST /api/v1/payment/subscription-watch/start``.
    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
    Currency:
      type: string
      enum:
      - usd
      - gbp
      - eur
      - inr
      - cad
      - cny
      - aud
      - rub
      - pln
      - brl
      - ils
      - try
      - jpy
      - chf
      - mxn
      - aed
      - sek
      - sgd
      - zar
      - nzd
      - thb
      - twd
      - czk
      - krw
      title: Currency
      description: Supported billing currencies as lowercase ISO 4217 codes.
    PricingByIpResponse:
      properties:
        ip:
          anyOf:
          - type: string
          - type: 'null'
          title: Ip
        location:
          anyOf:
          - $ref: '#/components/schemas/IPLocation'
          - type: 'null'
        currency:
          type: string
          title: Currency
        flag:
          anyOf:
          - type: string
          - type: 'null'
          title: Flag
        pricing:
          $ref: '#/components/schemas/CurrencyPricingResponse'
      type: object
      required:
      - currency
      - pricing
      title: PricingByIpResponse
      description: Full response for the GET /pricing/by-ip endpoint.
    ProductPricingResponse:
      properties:
        product_id:
          type: string
          title: Product Id
        price_id:
          type: string
          title: Price Id
        price:
          type: integer
          title: Price
        currency_factor:
          type: integer
          title: Currency Factor
      type: object
      required:
      - product_id
      - price_id
      - price
      - currency_factor
      title: ProductPricingResponse
      description: Stripe pricing details for a single product.
    SwitchPlanRequest:
      properties:
        plan:
          type: string
          title: Plan
      type: object
      required:
      - plan
      title: Switch Plan Request
      description: Request model for switching enterprise plans.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
  securitySchemes:
    ApiKeyHeaderPatched:
      type: apiKey
      in: header
      name: Authorization
    APIKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key