API referencePlatform APIEndpoint reference
GUIDE & REFERENCE

/api/webhooks/billing (management)

Source-derived management endpoint contract, authentication, request validation, responses, and errors.

This is the management service route. Its origin and authentication are described in Platform API overview and Authentication. A path shared by another service is a different endpoint.

PropertyContract
MethodsPOST, GET
Path/api/webhooks/billing
Path parametersNone
Query parameters read in routeNone read directly; schema validation below may define additional fields
Headers read in routeauthorization

Authentication and access

Webhook-specific signature or verification handler; not a customer bearer-token endpoint. See the handler and signing setup.

Request and response definitions

The following named definitions are imported or declared by this route. Optional markers, defaults, bounds, and enum values are shown exactly as implemented. A response type is a source contract, not an example populated with real account data.

BillingEventSchema

BillingEventSchema = z.object({
  eventType: z.enum([
    'subscription.created',
    'subscription.updated', 
    'subscription.cancelled',
    'subscription.deleted',
    'payment.succeeded',
    'payment.failed',
    'invoice.payment_succeeded',
    'invoice.payment_failed'
  ]),
  tenantId: z.string(),
  customerId: z.string().optional(),
  subscriptionId: z.string().optional(),
  plan: z.enum(['free', 'starter', 'pro', 'enterprise']),
  status: z.enum(['active', 'cancelled', 'past_due', 'unpaid']),
  currentPeriodStart: z.string().optional(),
  currentPeriodEnd: z.string().optional(),
  metadata: z.record(z.string()).optional()
})

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:39.

BillingEvent

type BillingEvent = z.infer<typeof BillingEventSchema>

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:60.

Method behavior

The handler excerpt preserves field validation, response envelopes, cookie changes, and exception branches. Values returned by service helpers retain their named response type above; for passthrough routes, the upstream response is authoritative.

POST

export async function POST(request: NextRequest) {
  const authError = requireBillingWebhookAuth(request)
  if (authError) {
    return authError
  }

  try {
    const body = await request.json()
    
    // Validate event schema
    const event = BillingEventSchema.parse(body)
    
    // Update tenant billing status
    await updateTenantBilling(event)
    
    return NextResponse.json({ received: true }, { status: 200 })
    
  } catch (error) {
    console.error('Billing webhook error:', error)
    
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { error: 'Invalid event schema', details: error.errors },
        { status: 400 }
      )
    }
    
    return NextResponse.json(
      { error: 'Webhook processing failed' },
      { status: 500 }
    )
  }
}

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:66.

GET

export async function GET() {
  return NextResponse.json({
    status: 'active',
    webhook: 'stripe',
    timestamp: new Date().toISOString()
  })
}

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:144.

Response and error branches

Literal HTTP statuses in the route: 200, 400, 401, 500, 503. Shared management error classes are defined in Errors and responses.

NextResponse.json(
      { error: 'Billing webhook not configured' },
      { status: 503 }
    )

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:24.

NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:32.

request.json()

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:73.

NextResponse.json({ received: true }, { status: 200 })

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:81.

NextResponse.json(
        { error: 'Invalid event schema', details: error.errors },
        { status: 400 }
      )

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:87.

NextResponse.json(
      { error: 'Webhook processing failed' },
      { status: 500 }
    )

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:93.

NextResponse.json({
    status: 'active',
    webhook: 'stripe',
    timestamp: new Date().toISOString()
  })

Source: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts:145.

Service dependencies

  • minds-ui/apps/api-service/lib/db.ts

Evidence

Generated from the local source snapshot on 2026-09-12. This page documents implemented code and does not certify a deployed service, permissions configuration, or successful provider operation.

Source file: minds-ui/apps/api-service/app/api/webhooks/billing/route.ts. SHA-256: 32a52641b1bccc8284636e3b87e0d8c7bbd7076fcec7ca226ce36f5092c36743.

On this page