Management APIs / Cloud Connect

Attach an existing project to an enrolled instance

POSThttps://api.spice.ai/v1/cloud-connect/attach

Attaches an existing standalone project to an enrolled standalone instance and assigns the project's region and cname from the stamp whose gateway terminates that instance's control stream. The optional location field is reserved for multi-region use and is ignored today. This operation is dual-authorized. A user-derived bearer plus the X-Org-Name assertion authorizes the project mutation; OAuth client credentials are refused. The caller must have the instances:write and apps:write scopes and the organization admin or owner role. The cert_pem and pop_sig body fields prove only that the request concerns the named instance. Instance proof by itself never authorizes project attachment. pop_sig is a base64 DER ECDSA (SHA-256) signature over the UTF-8 bytes spice-cloud-connect/attach/v1\n{X-Org-Name}\n{instance_id}\n{project_id}. The project must already have kind standalone and no cluster target. The database is the authority for attachment conflicts; clients must not pre-check or infer an attachment limit from this contract. Errors use {code, error, retryable}. A 409 always has retryable: false; a 5xx has retryable: true so the client exact replays any request whose attachment may already have committed.

Authorizations

  • AuthorizationstringRequired

    Bearer <token>. Authentication lists the tokens it accepts.

Header parameters

  • X-Org-NamestringRequired

    Organization that owns both the project and instance; also bound into pop_sig

    • Pattern: ^[A-Za-z0-9._-]{1,255}$

Body

application/jsonRequired

  • instance_idstringRequired

    Enrolled instance caller-facing id (inst_…)

    • Minimum length: 1
    • Maximum length: 200
  • project_idintegerRequired

    Existing standalone project id

    • Minimum: 1
    • Maximum: 9007199254740991
  • locationstring

    Reserved for multi-region use; accepted and ignored today

    • Minimum length: 1
    • Maximum length: 200
  • cert_pemstringRequired

    Cloud Connect identity certificate for instance_id

    • Minimum length: 1
    • Maximum length: 8192
  • pop_sigstringRequired

    Base64 DER ECDSA signature over the documented attach challenge

    • Minimum length: 1
    • Maximum length: 512

Responses

200Project attached, or exact same instance/project replay repairedapplication/json
  • instance_idstringRequired

  • organizationobjectRequired

    2 properties
    • idintegerRequired

    • namestringRequired

      Canonical organization name

  • projectobjectRequired

    2 properties
    • idintegerRequired

    • namestringRequired

      Canonical project name

  • monitor_urlstring (uri)Required

    Credential-free portal monitoring link for the project

    • Pattern: ^https://
400Invalid body or X-Org-Name (invalid_request or invalid_org_assertion)application/json
  • codestringRequired

    • Allowed values: invalid_request, invalid_org_assertion, unauthenticated, forbidden, org_forbidden, org_assertion_mismatch, org_deleted, invalid_instance_proof, instance_not_found, instance_not_enrolled, instance_already_attached, project_not_found, project_not_standalone, project_already_attached, internal
  • errorstringRequired

  • retryablebooleanRequired

401Unauthorizedapplication/json

Missing/invalid user bearer or invalid instance proof (unauthenticated or invalid_instance_proof)

  • codestringRequired

    • Allowed values: invalid_request, invalid_org_assertion, unauthenticated, forbidden, org_forbidden, org_assertion_mismatch, org_deleted, invalid_instance_proof, instance_not_found, instance_not_enrolled, instance_already_attached, project_not_found, project_not_standalone, project_already_attached, internal
  • errorstringRequired

  • retryablebooleanRequired

403Forbiddenapplication/json

Non-user bearer, insufficient scope, org access, or role refusal (forbidden, org_forbidden, org_assertion_mismatch, or org_deleted)

  • codestringRequired

    • Allowed values: invalid_request, invalid_org_assertion, unauthenticated, forbidden, org_forbidden, org_assertion_mismatch, org_deleted, invalid_instance_proof, instance_not_found, instance_not_enrolled, instance_already_attached, project_not_found, project_not_standalone, project_already_attached, internal
  • errorstringRequired

  • retryablebooleanRequired

404Not Foundapplication/json

Instance or project not found in the authorized organization (instance_not_found or project_not_found)

  • codestringRequired

    • Allowed values: invalid_request, invalid_org_assertion, unauthenticated, forbidden, org_forbidden, org_assertion_mismatch, org_deleted, invalid_instance_proof, instance_not_found, instance_not_enrolled, instance_already_attached, project_not_found, project_not_standalone, project_already_attached, internal
  • errorstringRequired

  • retryablebooleanRequired

409Conflictapplication/json

Instance not enrolled or already attached, project not standalone, or the database reports the project is already attached (instance_not_enrolled, instance_already_attached, project_not_standalone, or project_already_attached). These refusals carry retryable: false and prove this request did not commit an attachment.

  • codestringRequired

    • Allowed values: invalid_request, invalid_org_assertion, unauthenticated, forbidden, org_forbidden, org_assertion_mismatch, org_deleted, invalid_instance_proof, instance_not_found, instance_not_enrolled, instance_already_attached, project_not_found, project_not_standalone, project_already_attached, internal
  • errorstringRequired

  • retryablebooleanRequired

413Request body exceeds 1 MiB (invalid_request)application/json
  • codestringRequired

    • Allowed values: invalid_request, invalid_org_assertion, unauthenticated, forbidden, org_forbidden, org_assertion_mismatch, org_deleted, invalid_instance_proof, instance_not_found, instance_not_enrolled, instance_already_attached, project_not_found, project_not_standalone, project_already_attached, internal
  • errorstringRequired

  • retryablebooleanRequired

500Internal failure, including post-commit routing repair (internal, retryable)application/json
  • codestringRequired

    • Allowed values: invalid_request, invalid_org_assertion, unauthenticated, forbidden, org_forbidden, org_assertion_mismatch, org_deleted, invalid_instance_proof, instance_not_found, instance_not_enrolled, instance_already_attached, project_not_found, project_not_standalone, project_already_attached, internal
  • errorstringRequired

  • retryablebooleanRequired

OpenAPIapi.spice.ai/openapi.json

curl -X POST "https://api.spice.ai/v1/cloud-connect/attach" \
  -H "Authorization: Bearer <token>" \
  -H "X-Org-Name: <X-Org-Name>" \
  -H "Content-Type: application/json" \
  -d '{
    "instance_id": "string",
    "project_id": 1,
    "cert_pem": "string",
    "pop_sig": "string"
  }'
{
  "instance_id": "string",
  "organization": {
    "id": 0,
    "name": "string"
  },
  "project": {
    "id": 0,
    "name": "string"
  },
  "monitor_url": "https://example.com"
}

application/json