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
AuthorizationstringRequiredBearer <token>. Authentication lists the tokens it accepts.
Header parameters
X-Org-NamestringRequiredOrganization that owns both the project and instance; also bound into pop_sig
- Pattern:
^[A-Za-z0-9._-]{1,255}$
- Pattern:
Body
application/jsonRequired
instance_idstringRequiredEnrolled instance caller-facing id (
inst_…)- Minimum length:
1 - Maximum length:
200
- Minimum length:
project_idintegerRequiredExisting standalone project id
- Minimum:
1 - Maximum:
9007199254740991
- Minimum:
locationstringReserved for multi-region use; accepted and ignored today
- Minimum length:
1 - Maximum length:
200
- Minimum length:
cert_pemstringRequiredCloud Connect identity certificate for instance_id
- Minimum length:
1 - Maximum length:
8192
- Minimum length:
pop_sigstringRequiredBase64 DER ECDSA signature over the documented attach challenge
- Minimum length:
1 - Maximum length:
512
- Minimum length:
Responses
200Project attached, or exact same instance/project replay repairedapplication/json
instance_idstringRequiredorganizationobjectRequired2 properties
idintegerRequirednamestringRequiredCanonical organization name
projectobjectRequired2 properties
idintegerRequirednamestringRequiredCanonical project name
monitor_urlstring (uri)RequiredCredential-free portal monitoring link for the project
- Pattern:
^https://
- Pattern:
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
- Allowed values:
errorstringRequiredretryablebooleanRequired
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
- Allowed values:
errorstringRequiredretryablebooleanRequired
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
- Allowed values:
errorstringRequiredretryablebooleanRequired
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
- Allowed values:
errorstringRequiredretryablebooleanRequired
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
- Allowed values:
errorstringRequiredretryablebooleanRequired
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
- Allowed values:
errorstringRequiredretryablebooleanRequired
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
- Allowed values:
errorstringRequiredretryablebooleanRequired
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"
}'POST /v1/cloud-connect/attach HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
X-Org-Name: <X-Org-Name>
Content-Type: application/json
Content-Length: 95
{
"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
{
"code": "invalid_request",
"error": "string",
"retryable": true
}application/json
{
"code": "invalid_request",
"error": "string",
"retryable": true
}application/json
{
"code": "invalid_request",
"error": "string",
"retryable": true
}application/json
{
"code": "invalid_request",
"error": "string",
"retryable": true
}application/json
{
"code": "invalid_request",
"error": "string",
"retryable": true
}application/json
{
"code": "invalid_request",
"error": "string",
"retryable": true
}application/json
{
"code": "invalid_request",
"error": "string",
"retryable": true
}application/json