Files
sentryagent-idp/docs/openapi/billing.yaml
SentryAgent.ai Developer 7441c9f298 fix(vv): resolve all 6 V&V issues — field trial unblocked
All findings from the inaugural LeadValidator audit resolved and
confirmed. Release gate: PASS.

VV_ISSUE_002 (BLOCKER): 15 OpenAPI specs verified present covering
all 20 route groups (46 endpoints documented in docs/openapi/)

VV_ISSUE_003 (MAJOR): Remove any types from src/db/pool.ts —
replaced pool.query shim with unknown[] + Object.defineProperty,
zero any types, eslint-disable suppressions removed

VV_ISSUE_004 (MAJOR): Remove raw Pool from ScaffoldController and
HealthDetailedController — injected AgentRepository/CredentialRepository
and DbProbe interface respectively; added CredentialRepository.findActiveClientId()

VV_ISSUE_005 (MAJOR): Add unit tests for 5 untested services —
ComplianceStatusStore, EventPublisher, MarketplaceService,
OIDCTrustPolicyService, UsageService

VV_ISSUE_006 (MAJOR): Add integration tests for 7 missing route
groups — analytics, billing, tiers, webhooks, marketplace,
oidc-trust-policies, oidc-token-exchange

VV_ISSUE_001 (MINOR): Create missing design.md and tasks.md in 4
OpenSpec archives — all archives now complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 04:52:47 +00:00

356 lines
12 KiB
YAML

openapi: "3.0.3"
info:
title: SentryAgent.ai — Billing & Usage Metering
version: 1.0.0
description: |
Billing and usage metering endpoints for the SentryAgent.ai AgentIdP platform.
Integrates with **Stripe** for subscription and payment management.
**Authenticated endpoints** (require Bearer JWT):
- `POST /billing/checkout` — Create a Stripe Checkout Session for plan upgrades
- `GET /billing/usage` — Retrieve today's usage summary
**Unauthenticated endpoint** (Stripe webhook receiver):
- `POST /billing/webhook` — Receives Stripe webhook events (raw body + signature verification)
**Important:** The `/billing/webhook` endpoint uses `express.raw()` middleware
to receive the raw request body as a Buffer. Do not apply `express.json()` to this route.
The `Stripe-Signature` header is required for all webhook deliveries.
servers:
- url: http://localhost:3000/api/v1
description: Local development server
- url: https://api.sentryagent.ai/v1
description: Production server
tags:
- name: Billing Checkout
description: Stripe Checkout Session management
- name: Billing Webhook
description: Stripe webhook event receiver (unauthenticated)
- name: Usage
description: Usage metering and reporting
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT access token obtained via `POST /token`.
Include as `Authorization: Bearer <token>`.
schemas:
CheckoutRequest:
type: object
description: |
Optional request body for creating a Stripe Checkout Session.
When `successUrl` or `cancelUrl` are omitted, the platform generates
default redirect URLs pointing to the dashboard.
properties:
successUrl:
type: string
format: uri
description: URL to redirect to after successful payment.
example: "https://my-app.example.com/dashboard?billing=success"
cancelUrl:
type: string
format: uri
description: URL to redirect to if the user cancels checkout.
example: "https://my-app.example.com/dashboard?billing=cancel"
CheckoutResponse:
type: object
description: Stripe Checkout Session URL to redirect the user to.
required:
- checkoutUrl
properties:
checkoutUrl:
type: string
format: uri
description: |
Stripe-hosted Checkout page URL. Redirect the authenticated user
to this URL to complete payment.
example: "https://checkout.stripe.com/pay/cs_test_abcdef1234567890"
UsageSummary:
type: object
description: |
Today's usage summary for the authenticated organization.
Counters reset at UTC midnight.
required:
- organizationId
- date
- tokensIssued
- agentsRegistered
- credentialsGenerated
properties:
organizationId:
type: string
format: uuid
description: Organization the usage data belongs to.
example: "org-1234-5678-abcd-ef01"
date:
type: string
format: date
description: The calendar date (UTC) this summary covers.
example: "2026-04-07"
tokensIssued:
type: integer
description: Number of OAuth 2.0 tokens issued today.
minimum: 0
example: 4201
agentsRegistered:
type: integer
description: Number of new agents registered today.
minimum: 0
example: 3
credentialsGenerated:
type: integer
description: Number of new agent credentials generated today.
minimum: 0
example: 5
apiCallsTotal:
type: integer
description: Total API calls across all endpoints today.
minimum: 0
example: 12450
StripeWebhookResponse:
type: object
description: Acknowledgement response for a received Stripe webhook event.
required:
- received
properties:
received:
type: boolean
description: Always `true` when the webhook was processed successfully.
example: true
ErrorResponse:
type: object
description: Standard error response envelope.
required:
- code
- message
properties:
code:
type: string
example: "VALIDATION_ERROR"
message:
type: string
example: "Missing Stripe-Signature header."
details:
type: object
additionalProperties: true
responses:
Unauthorized:
description: Missing or invalid Bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: "UNAUTHORIZED"
message: "A valid Bearer token is required to access this resource."
Forbidden:
description: Valid token but insufficient permissions.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: "FORBIDDEN"
message: "You do not have permission to perform this action."
InternalServerError:
description: Unexpected server error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: "INTERNAL_SERVER_ERROR"
message: "An unexpected error occurred. Please try again later."
paths:
/billing/checkout:
post:
operationId: createBillingCheckoutSession
tags:
- Billing Checkout
summary: Create a Stripe Checkout Session
description: |
Creates a Stripe Checkout Session for the authenticated organization
to upgrade their subscription plan.
The organization ID is read from the `organization_id` claim in the
Bearer JWT — the caller does not need to provide it in the request body.
The `checkoutUrl` in the response is a Stripe-hosted checkout page.
Redirect the authenticated user to this URL to complete payment.
Requires a valid Bearer JWT. The `organization_id` claim must be present in the token.
security:
- BearerAuth: []
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/CheckoutRequest'
example:
successUrl: "https://my-app.example.com/dashboard?billing=success"
cancelUrl: "https://my-app.example.com/dashboard?billing=cancel"
responses:
'201':
description: Stripe Checkout Session created successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/CheckoutResponse'
example:
checkoutUrl: "https://checkout.stripe.com/pay/cs_test_abcdef1234567890"
'400':
description: Validation error — organization_id missing from token.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: "VALIDATION_ERROR"
message: "organization_id is required in token."
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
description: Unexpected error or Stripe API error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
code: "STRIPE_ERROR"
message: "Failed to create Stripe Checkout Session. Please try again."
/billing/webhook:
post:
operationId: handleStripeWebhook
tags:
- Billing Webhook
summary: Receive Stripe webhook events
description: |
Receives webhook events from Stripe's delivery system. This endpoint is
**unauthenticated** — authentication is provided by Stripe's HMAC signature
in the `Stripe-Signature` header.
**Body format:** The request body MUST be the raw JSON payload as sent by
Stripe (not parsed JSON). The `Content-Type` is `application/json` but
the body is read as a raw `Buffer` for signature verification.
**Signature verification:** The `Stripe-Signature` header is required.
If absent or invalid, the request is rejected with `400`.
**Supported events processed:**
- `checkout.session.completed` — Activates subscription after payment
- `customer.subscription.deleted` — Downgrades plan on cancellation
- `invoice.payment_failed` — Handles failed renewals
security: []
parameters:
- name: Stripe-Signature
in: header
required: true
description: |
HMAC signature from Stripe for payload verification.
Format: `t=<timestamp>,v1=<signature>,...`
schema:
type: string
example: "t=1492774577,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a05bd412fbc2a2bzo..."
requestBody:
required: true
content:
application/json:
schema:
type: object
description: Raw Stripe event payload (read as Buffer internally).
additionalProperties: true
example:
id: "evt_1234567890"
object: "event"
type: "checkout.session.completed"
data:
object:
id: "cs_test_abcdef1234567890"
customer: "cus_abc123"
responses:
'200':
description: Webhook event received and processed successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/StripeWebhookResponse'
example:
received: true
'400':
description: Missing or invalid Stripe-Signature header, or malformed payload.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
examples:
missingSignature:
summary: Missing Stripe-Signature header
value:
code: "VALIDATION_ERROR"
message: "Missing Stripe-Signature header."
invalidSignature:
summary: Signature verification failed
value:
code: "STRIPE_SIGNATURE_INVALID"
message: "Webhook signature verification failed."
'500':
$ref: '#/components/responses/InternalServerError'
/billing/usage:
get:
operationId: getBillingUsage
tags:
- Usage
summary: Get today's usage summary
description: |
Returns the usage summary for the authenticated organization
for the current calendar day (UTC).
Usage counters reset at UTC midnight.
The `organization_id` claim is read from the Bearer JWT.
Requires a valid Bearer JWT.
security:
- BearerAuth: []
responses:
'200':
description: Usage summary returned successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/UsageSummary'
example:
organizationId: "org-1234-5678-abcd-ef01"
date: "2026-04-07"
tokensIssued: 4201
agentsRegistered: 3
credentialsGenerated: 5
apiCallsTotal: 12450
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'