# /api/v1/regions/[slug] (management)

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

Source: https://docs.minds.sh/docs/api/platform/reference/management--api-v1-regions-slug



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, PATCH, DELETE                                                             |
| Path                           | `/api/v1/regions/[slug]`                                                       |
| Path parameters                | `slug`                                                                         |
| Query parameters read in route | None read directly; schema validation below may define additional fields       |
| Headers read in route          | No additional direct header reads; authentication helpers may read credentials |

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

### RegionResponse [#regionresponse]

```typescript
RegionResponse = z.object({
  id: z.string(),
  slug: z.string(),
  name: z.string(),
  displayName: z.string(),
  description: z.string().nullable(),
  provider: RegionProvider,
  status: RegionStatus,
  isPrimary: z.boolean(),
  ingressDomain: z.string().nullable(),
  latitude: z.number().nullable(),
  longitude: z.number().nullable(),
  capacity: RegionCapacity,
  lastHealthCheck: z.string().nullable(),
  healthMessage: z.string().nullable(),
})
```

Source: `minds-ui/apps/api-service/types/region.ts:44`.

### RegionResponse [#regionresponse-1]

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

Source: `minds-ui/apps/api-service/types/region.ts:60`.

### UpdateRegionRequest [#updateregionrequest]

```typescript
UpdateRegionRequest = z.object({
  name: z.string().min(1).max(100).optional(),
  displayName: z.string().min(1).max(200).optional(),
  description: z.string().max(500).optional(),
  status: RegionStatus.optional(),
  isPrimary: z.boolean().optional(),
  autoScales: z.boolean().optional(),
  maxTenants: z.number().positive().nullable().optional(),
  latitude: z.number().min(-90).max(90).optional(),
  longitude: z.number().min(-180).max(180).optional(),
})
```

Source: `minds-ui/apps/api-service/types/region.ts:103`.

### UpdateRegionRequest [#updateregionrequest-1]

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

Source: `minds-ui/apps/api-service/types/region.ts:114`.

### RouteParams [#routeparams]

```typescript
interface RouteParams {
  params: Promise<{ slug: string }>
}
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:20`.

## 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, { params }: RouteParams) {
  const requestId = generateRequestId()
  let rateLimitInfo: RateLimitMetadata | undefined
  const { slug } = await params

  try {
    const authContext = await resolveAuthContext(request)

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

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

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

    const region = await getRegionBySlug(authContext, slug)

    const response = apiSuccess<RegionResponse>(region)
    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 get region:', error)
    const response = apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to get region'),
      requestId
    )
    return withRequestMetadata(response, requestId, rateLimitInfo)
  }
}
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:28`.

### PATCH [#patch]

```typescript
export async function PATCH(request: NextRequest, { params }: RouteParams) {
  const requestId = generateRequestId()
  let rateLimitInfo: RateLimitMetadata | undefined
  const { slug } = await params

  try {
    const authContext = await resolveAuthContext(request)

    // TODO: Add admin check here
    // if (!authContext.isAdmin) {
    //   throw new ApiError(403, 'FORBIDDEN', 'Only admins can update regions')
    // }

    const body = await validateBody(request, UpdateRegionRequest)

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

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

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

    const region = await updateRegion(authContext, slug, body)

    const response = apiSuccess<RegionResponse>(region)
    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 update region:', error)
    const response = apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to update region'),
      requestId
    )
    return withRequestMetadata(response, requestId, rateLimitInfo)
  }
}
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:71`.

### DELETE [#delete]

```typescript
export async function DELETE(request: NextRequest, { params }: RouteParams) {
  const requestId = generateRequestId()
  let rateLimitInfo: RateLimitMetadata | undefined
  const { slug } = await params

  try {
    const authContext = await resolveAuthContext(request)

    // TODO: Add admin check here
    // if (!authContext.isAdmin) {
    //   throw new ApiError(403, 'FORBIDDEN', 'Only admins can delete regions')
    // }

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

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

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

    await deleteRegion(authContext, slug)

    const response = apiSuccess({ deleted: true })
    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 delete region:', error)
    const response = apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to delete region'),
      requestId
    )
    return withRequestMetadata(response, requestId, rateLimitInfo)
  }
}
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:122`.

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

Literal HTTP statuses in the route: 403, 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/regions/[slug]/route.ts:46`.

```typescript
apiSuccess<RegionResponse>(region)
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:51`.

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

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:55`.

```typescript
apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to get region'),
      requestId
    )
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:59`.

```typescript
new ApiError(500, 'INTERNAL_ERROR', 'Failed to get region')
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:60`.

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

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:96`.

```typescript
apiSuccess<RegionResponse>(region)
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:101`.

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

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:105`.

```typescript
apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to update region'),
      requestId
    )
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:109`.

```typescript
new ApiError(500, 'INTERNAL_ERROR', 'Failed to update region')
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:110`.

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

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:145`.

```typescript
apiSuccess({ deleted: true })
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:150`.

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

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:154`.

```typescript
apiError(
      new ApiError(500, 'INTERNAL_ERROR', 'Failed to delete region'),
      requestId
    )
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:158`.

```typescript
new ApiError(500, 'INTERNAL_ERROR', 'Failed to delete region')
```

Source: `minds-ui/apps/api-service/app/api/v1/regions/[slug]/route.ts:159`.

## 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/region.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/region-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/regions/[slug]/route.ts`. SHA-256: `f84ef61232e2bbbb7817ae6eaba4c55c0812aea84f8541e4dc006af29d531500`.
