Get started

Create a confidential-VM agent instance over the Confidential Agents API, wait for it to become ready, read its instance record, connect to it, and delete it.

This walkthrough creates an instance, waits until it is ready, reads its instance record, and deletes it. The examples use curl and jq.

Every endpoint, field, and error code is in the API reference.

This walkthrough creates an instance, waits until it is ready, reads its instance record, and deletes it. The examples use curl and jq.

1. Obtain credentials

Organizations and API keys are provisioned by Confidential. To request access, contact us.

When your organization is created, you receive:

  • An organization slug, used in instance hostnames such as {instance-name}.{organization-slug}.confidential.ai.
  • An API key, used as a Bearer token for API requests.

Export both values before running the examples:

export API_BASE="https://api.confidential.ai"
export ORGANIZATION_SLUG="acme"
export CA_API_KEY="confai_live_replace_with_your_key"

2. Test your API key

Call the usage endpoint. A successful response returns a data.pricing object and a data.usage object for the current billing cycle.

curl -sS "$API_BASE/v1/usage" \
  -H "Authorization: Bearer $CA_API_KEY" \
  | jq .

3. Create an instance

Use any valid OpenSSH public key (ssh-ed25519, ssh-rsa, ecdsa-sha2-*, etc.). We recommend ssh-ed25519 for new keys; ssh-rsa is supported for backwards compatibility but should be at least 2048 bits.

export SSH_PUBLIC_KEY="$(cat ~/.ssh/id_ed25519.pub)"

CREATE_RESPONSE="$(
  curl -sS -X POST "$API_BASE/v1/instances" \
    -H "Authorization: Bearer $CA_API_KEY" \
    -H "Content-Type: application/json" \
    --data "$(jq -n --arg public_key "$SSH_PUBLIC_KEY" '{
      public_key: $public_key,
      agent: "openclaw",
      inference_mode: "default_gateway"
    }')"
)"

echo "$CREATE_RESPONSE" | jq .

export INSTANCE_NAME="$(echo "$CREATE_RESPONSE" | jq -r '.data.name')"
export INSTANCE_HOSTNAME="$(echo "$CREATE_RESPONSE" | jq -r '.data.hostname')"

The create response is 202 Accepted. The instance starts in provisioning.

4. Get instance info

curl -sS "$API_BASE/v1/instances/$INSTANCE_NAME" \
  -H "Authorization: Bearer $CA_API_KEY" \
  | jq .

The response includes fields such as name, status, agent, hostname, inference_mode, created_at, and ready_at.

5. Poll until the instance is ready

There are no webhooks for instance state changes. Poll GET /v1/instances/{name} until status becomes ready.

while true; do
  INSTANCE_RESPONSE="$(
    curl -sS "$API_BASE/v1/instances/$INSTANCE_NAME" \
      -H "Authorization: Bearer $CA_API_KEY"
  )"

  STATUS="$(echo "$INSTANCE_RESPONSE" | jq -r '.data.status')"
  echo "status=$STATUS"

  if [ "$STATUS" = "ready" ]; then
    export INSTANCE_HOSTNAME="$(echo "$INSTANCE_RESPONSE" | jq -r '.data.hostname')"
    break
  fi

  if [ "$STATUS" = "failed" ]; then
    echo "$INSTANCE_RESPONSE" | jq .
    exit 1
  fi

  sleep 15
done

echo "Instance is ready: $INSTANCE_HOSTNAME"

Once the instance is ready, connect over SSH with the private key that matches the public key from the create request:

ssh -i ~/.ssh/id_ed25519 "$INSTANCE_HOSTNAME"

6. Verify the CVM attestation

ccvm is a CLI that runs inside the CVM and validates the hardware attestation, TPM measurements, host-key fingerprints, and inference gateway attestation chain — confirming the CVM is what it claims to be and is connected to the expected gateway. Run it from within the SSH session immediately after claiming the instance.

ccvm verify

Example output:

[1/5] SEV-SNP Hardware              PASS
[2/5] TPM Attestation               PASS
[3/5] Host Key Binding              PASS
[4/5] Inference Provider            PASS
[5/5] External Access Lockout       PASS  (FAIL on staging — debug SSH access intentional)

The tool is open source: github.com/confidential-dot-ai/confidential-cvm-cli.

7. Delete the instance

When you are done, delete the instance. The response is 202 Accepted with status: terminating. The instance reaches terminated asynchronously once Azure resources are cleaned up.

curl -sS -X DELETE "$API_BASE/v1/instances/$INSTANCE_NAME" \
  -H "Authorization: Bearer $CA_API_KEY" \
  | jq .

Next steps