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>
342 lines
11 KiB
YAML
342 lines
11 KiB
YAML
openapi: "3.0.3"
|
|
|
|
info:
|
|
title: SentryAgent.ai — Tier Management
|
|
version: 1.0.0
|
|
description: |
|
|
Tier status and upgrade endpoints for the SentryAgent.ai AgentIdP platform.
|
|
|
|
The tier system defines per-organization limits on agents, tokens, and API calls.
|
|
|
|
**All endpoints require a valid Bearer JWT.**
|
|
|
|
**Available tiers:**
|
|
| Tier | Max Agents | Max Tokens/Month | Rate Limit |
|
|
|------|-----------|-----------------|------------|
|
|
| `free` | 100 | 10,000 | 100 req/min |
|
|
| `pro` | 1,000 | 100,000 | 1,000 req/min |
|
|
| `enterprise` | unlimited | unlimited | custom |
|
|
|
|
servers:
|
|
- url: http://localhost:3000/api/v1
|
|
description: Local development server
|
|
- url: https://api.sentryagent.ai/v1
|
|
description: Production server
|
|
|
|
tags:
|
|
- name: Tiers
|
|
description: Tier status and upgrade management
|
|
|
|
components:
|
|
securitySchemes:
|
|
BearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
description: |
|
|
JWT access token obtained via `POST /token`.
|
|
Include as `Authorization: Bearer <token>`.
|
|
|
|
schemas:
|
|
PlanTier:
|
|
type: string
|
|
enum:
|
|
- free
|
|
- pro
|
|
- enterprise
|
|
description: Current subscription plan tier.
|
|
example: free
|
|
|
|
TierLimits:
|
|
type: object
|
|
description: Hard limits defined by the current tier.
|
|
required:
|
|
- maxAgents
|
|
- maxTokensPerMonth
|
|
- rateLimitPerMinute
|
|
properties:
|
|
maxAgents:
|
|
type: integer
|
|
description: Maximum number of agents allowed for this organization.
|
|
example: 100
|
|
maxTokensPerMonth:
|
|
type: integer
|
|
description: Maximum OAuth 2.0 token requests per calendar month.
|
|
example: 10000
|
|
rateLimitPerMinute:
|
|
type: integer
|
|
description: Maximum API requests per minute.
|
|
example: 100
|
|
|
|
TierUsage:
|
|
type: object
|
|
description: Live usage counters for the current billing period.
|
|
required:
|
|
- agentsRegistered
|
|
- tokensThisMonth
|
|
- requestsThisMinute
|
|
properties:
|
|
agentsRegistered:
|
|
type: integer
|
|
description: Current number of active (non-decommissioned) agents.
|
|
minimum: 0
|
|
example: 47
|
|
tokensThisMonth:
|
|
type: integer
|
|
description: Total OAuth 2.0 tokens issued in the current calendar month.
|
|
minimum: 0
|
|
example: 3214
|
|
requestsThisMinute:
|
|
type: integer
|
|
description: API requests in the current rate-limit window.
|
|
minimum: 0
|
|
example: 12
|
|
|
|
TierStatus:
|
|
type: object
|
|
description: Full tier status response — current tier, plan limits, and live usage.
|
|
required:
|
|
- organizationId
|
|
- tier
|
|
- limits
|
|
- usage
|
|
properties:
|
|
organizationId:
|
|
type: string
|
|
format: uuid
|
|
description: Organization the tier status applies to.
|
|
example: "org-1234-5678-abcd-ef01"
|
|
tier:
|
|
$ref: '#/components/schemas/PlanTier'
|
|
limits:
|
|
$ref: '#/components/schemas/TierLimits'
|
|
usage:
|
|
$ref: '#/components/schemas/TierUsage'
|
|
billingPeriodStart:
|
|
type: string
|
|
format: date
|
|
description: First day of the current billing period (UTC).
|
|
example: "2026-04-01"
|
|
billingPeriodEnd:
|
|
type: string
|
|
format: date
|
|
description: Last day of the current billing period (UTC).
|
|
example: "2026-04-30"
|
|
|
|
TierUpgradeRequest:
|
|
type: object
|
|
description: Request body for initiating a tier upgrade.
|
|
required:
|
|
- targetTier
|
|
properties:
|
|
targetTier:
|
|
type: string
|
|
enum:
|
|
- pro
|
|
- enterprise
|
|
description: |
|
|
The target plan tier to upgrade to.
|
|
Downgrading is not permitted via this endpoint.
|
|
example: "pro"
|
|
successUrl:
|
|
type: string
|
|
format: uri
|
|
description: |
|
|
URL to redirect to after successful payment.
|
|
Defaults to the platform dashboard when omitted.
|
|
example: "https://my-app.example.com/dashboard?upgrade=success"
|
|
cancelUrl:
|
|
type: string
|
|
format: uri
|
|
description: |
|
|
URL to redirect to if the user cancels checkout.
|
|
Defaults to the platform dashboard when omitted.
|
|
example: "https://my-app.example.com/dashboard?upgrade=cancel"
|
|
|
|
TierUpgradeResponse:
|
|
type: object
|
|
description: Stripe Checkout URL to initiate the tier upgrade payment flow.
|
|
required:
|
|
- checkoutUrl
|
|
- targetTier
|
|
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"
|
|
targetTier:
|
|
$ref: '#/components/schemas/PlanTier'
|
|
|
|
ErrorResponse:
|
|
type: object
|
|
description: Standard error response envelope.
|
|
required:
|
|
- code
|
|
- message
|
|
properties:
|
|
code:
|
|
type: string
|
|
example: "UNAUTHORIZED"
|
|
message:
|
|
type: string
|
|
example: "A valid Bearer token is required to access this resource."
|
|
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."
|
|
|
|
security:
|
|
- BearerAuth: []
|
|
|
|
paths:
|
|
/tiers/status:
|
|
get:
|
|
operationId: getTierStatus
|
|
tags:
|
|
- Tiers
|
|
summary: Get current tier status
|
|
description: |
|
|
Returns the current tier, plan limits, and live usage counters for the
|
|
authenticated organization.
|
|
|
|
The organization ID is derived from the `organization_id` claim in the
|
|
Bearer JWT — no explicit organization ID is required in the request.
|
|
|
|
Use this endpoint to:
|
|
- Display the current plan in your dashboard
|
|
- Check remaining quota before performing bulk operations
|
|
- Determine whether an upgrade is needed
|
|
responses:
|
|
'200':
|
|
description: Tier status returned successfully.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TierStatus'
|
|
example:
|
|
organizationId: "org-1234-5678-abcd-ef01"
|
|
tier: "free"
|
|
limits:
|
|
maxAgents: 100
|
|
maxTokensPerMonth: 10000
|
|
rateLimitPerMinute: 100
|
|
usage:
|
|
agentsRegistered: 47
|
|
tokensThisMonth: 3214
|
|
requestsThisMinute: 12
|
|
billingPeriodStart: "2026-04-01"
|
|
billingPeriodEnd: "2026-04-30"
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'500':
|
|
$ref: '#/components/responses/InternalServerError'
|
|
|
|
/tiers/upgrade:
|
|
post:
|
|
operationId: initiateTierUpgrade
|
|
tags:
|
|
- Tiers
|
|
summary: Initiate a tier upgrade via Stripe
|
|
description: |
|
|
Initiates a Stripe Checkout Session for upgrading the organization's plan tier.
|
|
|
|
The returned `checkoutUrl` is a Stripe-hosted payment page.
|
|
Redirect the authenticated user to this URL to complete the upgrade payment.
|
|
|
|
After successful payment, Stripe notifies the platform via the
|
|
`POST /billing/webhook` endpoint, which activates the new tier automatically.
|
|
|
|
**Constraints:**
|
|
- Only upgrades are supported (free → pro, free → enterprise, pro → enterprise).
|
|
- Attempting to "upgrade" to the current or lower tier returns `400`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TierUpgradeRequest'
|
|
example:
|
|
targetTier: "pro"
|
|
successUrl: "https://my-app.example.com/dashboard?upgrade=success"
|
|
cancelUrl: "https://my-app.example.com/dashboard?upgrade=cancel"
|
|
responses:
|
|
'201':
|
|
description: Stripe Checkout Session created successfully. Redirect user to checkoutUrl.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TierUpgradeResponse'
|
|
example:
|
|
checkoutUrl: "https://checkout.stripe.com/pay/cs_test_abcdef1234567890"
|
|
targetTier: "pro"
|
|
'400':
|
|
description: Invalid upgrade request — already on target tier or attempting a downgrade.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
examples:
|
|
alreadyOnTier:
|
|
summary: Already on target tier
|
|
value:
|
|
code: "ALREADY_ON_TIER"
|
|
message: "Your organization is already on the 'pro' tier."
|
|
invalidDowngrade:
|
|
summary: Downgrade not permitted
|
|
value:
|
|
code: "DOWNGRADE_NOT_PERMITTED"
|
|
message: "Downgrading tiers is not supported via this endpoint."
|
|
missingOrgId:
|
|
summary: Missing organization_id in token
|
|
value:
|
|
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 failure.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
example:
|
|
code: "STRIPE_ERROR"
|
|
message: "Failed to create Stripe Checkout Session. Please try again."
|