# /api/v1/tenants/[id]/backups (management)

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

Source: https://docs.minds.sh/docs/api/platform/reference/management--api-v1-tenants-id-backups



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                        | GET, POST                                                                |
| Path                           | `/api/v1/tenants/[id]/backups`                                           |
| Path parameters                | `id`                                                                     |
| Query parameters read in route | None read directly; schema validation below may define additional fields |
| Headers read in route          | `content-length`                                                         |

## Authentication and access [#authentication-and-access]

Management auth context: validated x-api-key or configured session authentication; trusted gateway integration may select its auth pipeline. Organization/tenant checks are separate.

## 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.

### CreateBackupRequest [#createbackuprequest]

```typescript
CreateBackupRequest = z.object({
  name: z.string().max(100).optional(),
  description: z.string().max(500).optional(),
})
```

Source: `minds-ui/apps/api-service/types/backup.ts:14`.

### CreateBackupRequest [#createbackuprequest-1]

```typescript
export type CreateBackupRequest = z.infer<typeof CreateBackupRequest>
```

Source: `minds-ui/apps/api-service/types/backup.ts:19`.

### RouteContext [#routecontext]

```typescript
interface RouteContext {
  params: Promise<{ id: string }>
}
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:22`.

## 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.

### GET [#get]

```typescript
export async function GET(request: NextRequest, context: RouteContext) {
  const requestId = generateRequestId()
  const { id } = await context.params
  let rateLimitInfo: RateLimitMetadata | undefined

  try {
    const tenantId = validateTenantId(id)
    const authContext = await resolveAuthContext(request)
    const evaluation = await enforceRateLimit({
      context: authContext,
      tenantId,
    })

    rateLimitInfo = {
      ...evaluation.metadata,
      retryAfter: evaluation.retryAfter,
    }

    if (evaluation.blocked) {
      throw new RateLimitExceededError(evaluation.retryAfter ?? 60)
    }

    const backups = await listBackups(authContext, tenantId)
    const response = apiSuccess(backups)
    return withRequestMetadata(response, requestId, rateLimitInfo)
  } catch (error) {
    if (error instanceof ApiError) {
      const response = apiError(error, requestId)
      return withRequestMetadata(response, requestId, rateLimitInfo)
    }
    console.error('Failed to list backups:', error)
    const response = apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to list backups'),
      requestId,
    )
    return withRequestMetadata(response, requestId, rateLimitInfo)
  }
}
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:26`.

### POST [#post]

```typescript
export async function POST(request: NextRequest, context: RouteContext) {
  const requestId = generateRequestId()
  const { id } = await context.params
  let rateLimitInfo: RateLimitMetadata | undefined

  try {
    const tenantId = validateTenantId(id)
    const authContext = await resolveAuthContext(request)

    let payload: CreateBackupRequest | undefined
    const contentLength = request.headers.get('content-length')
    if (contentLength === null || contentLength === '0') {
      payload = {}
    } else {
      payload = await validateBody(request, CreateBackupRequest)
    }

    const evaluation = await enforceRateLimit({
      context: authContext,
      tenantId,
    })

    rateLimitInfo = {
      ...evaluation.metadata,
      retryAfter: evaluation.retryAfter,
    }

    if (evaluation.blocked) {
      throw new RateLimitExceededError(evaluation.retryAfter ?? 60)
    }

    const response = await createBackup(authContext, tenantId, payload)
    const payloadResponse = apiAccepted(response)
    return withRequestMetadata(payloadResponse, requestId, rateLimitInfo)
  } catch (error) {
    if (error instanceof ApiError) {
      const response = apiError(error, requestId)
      return withRequestMetadata(response, requestId, rateLimitInfo)
    }
    console.error('Failed to create backup:', error)
    const response = apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to create backup'),
      requestId,
    )
    return withRequestMetadata(response, requestId, rateLimitInfo)
  }
}
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:65`.

## Response and error branches [#response-and-error-branches]

Literal HTTP statuses in the route: 500. Shared management error classes are defined in [Errors and responses](/docs/api/platform/errors).

```typescript
new RateLimitExceededError(evaluation.retryAfter ?? 60)
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:45`.

```typescript
apiSuccess(backups)
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:49`.

```typescript
apiError(error, requestId)
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:53`.

```typescript
apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to list backups'),
      requestId,
    )
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:57`.

```typescript
new ApiError(500, 'INTERNAL_ERROR', 'Failed to list backups')
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:58`.

```typescript
new RateLimitExceededError(evaluation.retryAfter ?? 60)
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:93`.

```typescript
apiAccepted(response)
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:97`.

```typescript
apiError(error, requestId)
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:101`.

```typescript
apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to create backup'),
      requestId,
    )
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:105`.

```typescript
new ApiError(500, 'INTERNAL_ERROR', 'Failed to create backup')
```

Source: `minds-ui/apps/api-service/app/api/v1/tenants/[id]/backups/route.ts:106`.

## Service dependencies [#service-dependencies]

* `minds-ui/apps/api-service/lib/api-response.ts`
* `minds-ui/apps/api-service/lib/validation.ts`
* `minds-ui/apps/api-service/types/backup.ts`
* `minds-ui/apps/api-service/types/errors.ts`
* `minds-ui/apps/api-service/lib/services/auth-context.ts`
* `minds-ui/apps/api-service/lib/services/backup-service.ts`
* `minds-ui/apps/api-service/lib/services/rate-limit.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/v1/tenants/[id]/backups/route.ts`. SHA-256: `4e70f7a9bb9e8e28ce8b5db59de521e0bf61feaa61f137f761e28a04730a4786`.
