# List projects available for Cloud Connect attachment

`GET /v1/cloud-connect/attachable-projects`

Returns every project the authenticated caller may attach an enrolled Cloud Connect instance to. Policy is evaluated entirely by the server: today, results include only live, unattached standalone projects in the resolved organization, and user credentials require that organization's owner or admin role. Exactly one organization is searched per request and the response names it in `org`, so an empty `projects` states which organization has no eligible project rather than leaving a client to wonder whether the one it meant was searched at all; name another with `X-Org-Name`. Clients must render every returned project and instance without applying their own eligibility filters. The `instances` array is part of the stable contract and may be populated when server policy permits projects with existing attachments.

## Query parameters

- `limit` (integer, optional): Maximum number of projects to return. Default: `50`. Minimum: `1`. Maximum: `100`.
- `cursor` (string, optional): Opaque cursor returned as `next_cursor` by the previous page.

## Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): Organization to list. A user token may name any organization its owner belongs to; naming one they do not is `org_forbidden`. Never ignored: a token bound to one organization that names another is `org_assertion_mismatch`. A portal session token is bound to none and must send it (`org_assertion_required`). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

## Example request

```bash
curl "https://api.spice.ai/v1/cloud-connect/attachable-projects" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/cloud-connect/attachable-projects HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

## Responses

**200 OK**

A page of projects currently eligible for attachment.

Content type: `application/json`

- `org` (string, required): Handle of the organization the page was scoped to, being the one `X-Org-Name` named or the credential's own when it named none. Always present, so an empty `projects` says which organization has no eligible project rather than leaving a client to guess whether its active organization was the one searched.
- `projects` (array of object, required)
  - `id` (integer (int64), required)
  - `name` (string, required)
  - `org` (string, required): Organization handle.
  - `region` (string | null, required): Project control-plane region, if assigned.
  - `instances` (array of object, required)
    - `id` (string, required): Instance external identifier.
    - `location` (string | null, required): Customer-declared instance location.
    - `enrolled_at` (string (date-time) | null, required)
- `next_cursor` (string | null, required): Opaque cursor for the next page, or null at the end.

**400 Bad Request**

Invalid organization assertion (`invalid_org_assertion`), none from a portal session (`org_assertion_required`), or invalid limit/cursor (`invalid_pagination`).

**401 Unauthorized**

Missing or invalid bearer token.

**403 Forbidden**

Organization access (`org_forbidden`, `org_assertion_mismatch`, or `org_deleted`), apps:read scope (`insufficient_scope`), or owner/admin role (`forbidden`) was refused.

**500 Internal Server Error**

Organization role, project, or organization-handle lookup failed.

OpenAPI: [api.spice.ai/openapi.json](https://api.spice.ai/openapi.json)
