# /api/organizations (dashboard)

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

Source: https://docs.minds.sh/docs/api/platform/reference/dashboard--api-organizations



This is the **dashboard** 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/organizations`                                                           |
| Path parameters                | None                                                                           |
| 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]

Dashboard session cookie through @repo/auth/server. Some auth-summary routes can redirect to sign-in; inspect the status branches below.

## 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() {
  try {
    const session = await getSession();
    if (!session) {
      return NextResponse.json(
        { error: { code: 'UNAUTHENTICATED', message: 'Sign in at auth.l1fe.ai.' } },
        { status: 401 }
      );
    }

    const cookieStore = await cookies();
    const organizationContext = await loadMindsOrganizationContext({
      accessToken: session.accessToken,
      activeTenantId: cookieStore.get(ACTIVE_TENANT_COOKIE)?.value,
      tokenOrgId: session.user.orgId,
      tokenTenantId: session.user.tenantId,
    });

    return NextResponse.json(
      {
        organizations: organizationContext.organizations,
        activeOrganizationId: organizationContext.activeOrganizationId,
        tenants: organizationContext.tenantGroups,
      },
      {
        headers: {
          'Cache-Control': 'private, no-cache, no-store, must-revalidate',
        },
      }
    );
  } catch (error) {
    console.error('Failed to fetch organizations:', error);
    return NextResponse.json(
      {
        error: {
          code: 'FETCH_FAILED',
          message: error instanceof Error ? error.message : 'Failed to fetch organizations',
        },
      },
      { status: 500 }
    );
  }
}
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:17`.

### POST [#post]

```typescript
export async function POST(request: NextRequest) {
  try {
    const session = await getSession();
    if (!session) {
      return NextResponse.json(
        { error: { code: 'UNAUTHENTICATED', message: 'Sign in at auth.l1fe.ai.' } },
        { status: 401 }
      );
    }

    const body = await request.json().catch(() => ({}));
    const parsed = parseCreateOrganizationBody(body);
    if (!parsed.ok) {
      return NextResponse.json(
        { error: { code: 'INVALID_REQUEST', message: parsed.message } },
        { status: 400 }
      );
    }

    const organization = await createMindsOrganization({
      accessToken: session.accessToken,
      name: parsed.name,
      slug: parsed.slug,
    });

    const cookieStore = await cookies();
    cookieStore.set(ACTIVE_TENANT_COOKIE, organization.id, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      maxAge: COOKIE_MAX_AGE,
      path: '/',
    });

    return NextResponse.json(
      {
        organization,
        activeOrganizationId: organization.id,
      },
      {
        status: 201,
        headers: {
          'Cache-Control': 'private, no-cache, no-store, must-revalidate',
        },
      }
    );
  } catch (error) {
    console.error('Failed to create organization:', error);
    if (error instanceof MindsOrganizationError) {
      return NextResponse.json(
        {
          error: {
            code: 'CREATE_FAILED',
            message: error.message,
          },
        },
        { status: normalizeErrorStatus(error.status, 502) }
      );
    }

    return NextResponse.json(
      {
        error: {
          code: 'CREATE_FAILED',
          message: error instanceof Error ? error.message : 'Failed to create organization',
        },
      },
      { status: 500 }
    );
  }
}
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:61`.

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

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

```typescript
NextResponse.json(
        { error: { code: 'UNAUTHENTICATED', message: 'Sign in at auth.l1fe.ai.' } },
        { status: 401 }
      )
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:21`.

```typescript
NextResponse.json(
      {
        organizations: organizationContext.organizations,
        activeOrganizationId: organizationContext.activeOrganizationId,
        tenants: organizationContext.tenantGroups,
      },
      {
        headers: {
          'Cache-Control': 'private, no-cache, no-store, must-revalidate',
        },
      }
    )
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:35`.

```typescript
NextResponse.json(
      {
        error: {
          code: 'FETCH_FAILED',
          message: error instanceof Error ? error.message : 'Failed to fetch organizations',
        },
      },
      { status: 500 }
    )
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:49`.

```typescript
NextResponse.json(
        { error: { code: 'UNAUTHENTICATED', message: 'Sign in at auth.l1fe.ai.' } },
        { status: 401 }
      )
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:65`.

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

Source: `minds-ui/apps/app/app/api/organizations/route.ts:71`.

```typescript
NextResponse.json(
        { error: { code: 'INVALID_REQUEST', message: parsed.message } },
        { status: 400 }
      )
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:74`.

```typescript
NextResponse.json(
      {
        organization,
        activeOrganizationId: organization.id,
      },
      {
        status: 201,
        headers: {
          'Cache-Control': 'private, no-cache, no-store, must-revalidate',
        },
      }
    )
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:95`.

```typescript
NextResponse.json(
        {
          error: {
            code: 'CREATE_FAILED',
            message: error.message,
          },
        },
        { status: normalizeErrorStatus(error.status, 502) }
      )
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:110`.

```typescript
NextResponse.json(
      {
        error: {
          code: 'CREATE_FAILED',
          message: error instanceof Error ? error.message : 'Failed to create organization',
        },
      },
      { status: 500 }
    )
```

Source: `minds-ui/apps/app/app/api/organizations/route.ts:121`.

## Service dependencies [#service-dependencies]

* `minds-ui/apps/app/lib/organizations.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/app/app/api/organizations/route.ts`. SHA-256: `9e5edc48f58f4cfa43b63aeba4832e0a36f37d0b037ea281552523c1e1925320`.
