# /api/webhooks/billing (management)

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

Source: https://docs.minds.sh/docs/api/platform/reference/management--api-webhooks-billing



This is the **management** service route. Its origin and authentication are described in [Platform API overview](/docs/api/platform) and [Authentication](/docs/api/platform/authentication). A path shared by another service is a different endpoint.

| Property                       | Contract                                                                 |
| ------------------------------ | ------------------------------------------------------------------------ |
| Methods                        | POST, GET                                                                |
| Path                           | `/api/webhooks/billing`                                                  |
| Path parameters                | None                                                                     |
| Query parameters read in route | None read directly; schema validation below may define additional fields |
| Headers read in route          | `authorization`                                                          |

## Authentication and access [#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 [#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]

```typescript
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 [#billingevent]

```typescript
type BillingEvent = z.infer<typeof BillingEventSchema>
```

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

## Method behavior [#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 [#post]

```typescript
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 [#get]

```typescript
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 [#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](/docs/api/platform/errors).

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

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

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

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

```typescript
request.json()
```

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

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

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

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

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

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

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

```typescript
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 [#service-dependencies]

* `minds-ui/apps/api-service/lib/db.ts`

## Evidence [#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`.
