Internal Documentation internal
TalkIDE internal documentation

Authenticated user retrieves their current default payment method (card brand, last4, expiry) and billing email from Stripe. Requires a valid JWT access token.

  • Data is fetched live from Stripe Customer.invoice_settings.default_payment_method — not cached in TalkIDE DB.
  • If no default payment method is registered, the endpoint returns null for all card fields and the user’s account email as billingEmail.
  • If stripe_customer_id is null (user has never performed any billing action), the endpoint returns the “no payment method” placeholder without creating a Stripe Customer.
  • This endpoint is called on mount of BillingSection.vue to populate the payment method row.
  • Related: UC-10001 — registration flow. UC-10003 — billing email update.
sequenceDiagram
    actor User

    User->>+FE: opens Profile → Billing & Usage section

    FE->>FE: onMounted — trigger billing data load

    FE->>+BE: GET /api/v1/users/me/billing/payment-method <br> Authorization: Bearer {accessToken}

    BE->>BE: validate JWT access token
    alt access token invalid or missing
        BE-->>FE: 401 Unauthorized <br> ErrorResponse
    end

    BE->>DB: SELECT stripe_customer_id FROM users WHERE id = userId

    alt stripe_customer_id is null
        BE-->>FE: 200 OK <br> PaymentMethodResponse (all card fields null)
    end

    BE->>Stripe: stripe.customers.retrieve(customerId, { expand: ["invoice_settings.default_payment_method"] })
    Stripe-->>BE: Customer { invoice_settings: { default_payment_method: PaymentMethod | null } }

    alt no default payment method on Customer
        BE-->>FE: 200 OK <br> PaymentMethodResponse (all card fields null)
    end

    BE->>-FE: 200 OK <br> PaymentMethodResponse

    FE->>-User: display card brand + last4 + expiry + billing email

GET /api/v1/users/me/billing/payment-method (no request body; authentication via JWT Bearer token)

200 OK PaymentMethodResponse (card registered):

{
  "brand": "visa",
  "last4": "4242",
  "expMonth": 12,
  "expYear": 2028,
  "billingEmail": "jane@example.com"
}

200 OK PaymentMethodResponse (no card registered):

{
  "brand": null,
  "last4": null,
  "expMonth": null,
  "expYear": null,
  "billingEmail": "jane@example.com"
}

401 Unauthorized ErrorResponse:

{
  "status": 401,
  "code": "AUTHENTICATION_FAILED",
  "message": "Access token is missing or invalid"
}

502 Bad Gateway (Stripe API unreachable) ErrorResponse:

{
  "status": 502,
  "code": "STRIPE_UNAVAILABLE",
  "message": "Payment provider is temporarily unavailable. Please try again."
}

Frontend

Validations

Field / ControlConstraintsNote
Payment method displayrender placeholder “No payment method” when all card fields nullFE checks brand === null

UX Guidelines

Payment method row states:

StateDisplay
LoadingSkeleton row (shimmer)
No card registered”No payment method on file” text (fg-3) + “Add card” button (primary)
Card registeredBrand icon + ”•••• {last4}” + “Expires {expMonth}/{expYear}” + “Change” button (ghost)
Error (502)Toast (rose, 5s): “Could not load payment method. Please try again.”

Brand icon mapping (FE-side, CSS class or SVG asset):

brand valueDisplay label
visaVisa
mastercardMastercard
amexAmerican Express
discoverDiscover
(other)capitalize brand value

Backend

Validations

FieldConstraintsNote
JWT Authorization headernot_blank, valid signature, not expired401 if missing/invalid

Test Cases

GIVENWHENTHEN
Authenticated user with no stripe_customer_idGET /payment-method is called200 OK; all card fields null; billingEmail = user account email
Authenticated user with stripe_customer_id but no default payment methodGET /payment-method is called200 OK; all card fields null; billingEmail from Stripe Customer email
Authenticated user with Stripe test card 4242 set as defaultGET /payment-method is called200 OK; brand = “visa”, last4 = “4242”, expMonth/expYear populated; billingEmail from Stripe Customer
No Authorization headerGET /payment-method is called401 AUTHENTICATION_FAILED returned
Stripe API unreachableGET /payment-method is called502 STRIPE_UNAVAILABLE returned
User with stripe_customer_id that no longer exists in Stripe (edge case)GET /payment-method is called502 STRIPE_UNAVAILABLE returned (or treat as no payment method — log warning, return null fields)

Was this page helpful?

Thanks for the feedback.