Every Excloud product is backed by an HTTP API. The CLI, console, and Terraform provider all sit on top of these. This page covers the contract that’s the same across every service; per-service Swagger UIs are linked at the bottom.

Base URLs

ServiceBase URLSpec
Computehttps://compute.excloud.inSwagger
IAMhttps://iam.excloud.inSwagger
DNShttps://dns.excloud.inSwagger
Databasehttps://database.excloud.inSwagger
Object Storage (control)https://buckets.excloud.inSwagger
Object Storage (S3)https://<org-id>.buckets.excloud.inS3 v4 signatures
Secretshttps://secrets.excloud.inSwagger
Kuberneteshttps://k8sapi.excloud.inSwagger

All services speak JSON over HTTPS. The S3 endpoint on object storage is the exception — it speaks the S3 protocol so existing tools (aws s3, MinIO client, boto3, rclone) work unchanged.

Authentication

Every request to a control-plane API carries a bearer token:

Authorization: Bearer <token>

You can get a token three ways:

  1. exc login — interactive flow, writes a long-lived access token to ~/.exc/config. Best for laptops.
  2. API key — create one with exc apikey create (or in the console). Best for scripts and CI.
  3. Service account — exc serviceaccount creates a non-human identity that policies can bind to. Best for production workloads and least-privilege automation.

Tokens are scoped to one org at a time. The exc login flow records the active org alongside the token; for API keys and service accounts the org is fixed at creation.

What each one can do is controlled by IAM policy. See the Policies guide and Permissions Reference.

Error format

Errors are JSON with a stable shape:

{
  "error": {
    "code": "compute.instance.not_found",
    "message": "instance 42 not found",
    "request_id": "01HE9X…"
  }
}
  • code is a dotted identifier safe to switch on.
  • message is human-readable; don’t parse it.
  • request_id is what to quote when emailing support.
  • HTTP status follows the usual rules: 400 for client errors, 401 unauthenticated, 403 denied by policy, 404 not found, 409 conflict, 429 rate-limited, 5xx server-side.

Regions and zones

Excloud is single-region (Mumbai, mum) with one zone today (mum-1a, zone_id=1). Inside the region, resources live in zones. List endpoints that span zones (/compute/list, /database/list, /subnet/list) accept a zone_id query parameter; omit it to query across all zones. The API surface already takes zone_id so your code doesn’t change when more zones come online.

Async operations and --wait

Create, restart, stop, terminate, resize, and similar verbs return as soon as the request is accepted. The actual work happens asynchronously and you need to poll for terminal state.

Two patterns are supported:

  1. Poll yourself — call GET /<resource>/<id> and inspect the status field. Terminal states are running, stopped, terminated, error. Poll every few seconds.
  2. Use --wait — the CLI does the polling for you. The Terraform provider does the same automatically, with a 30-minute default timeout.

There’s no separate “operations” resource; the request returns the new resource ID immediately and you poll the resource itself.

Pagination

Most list endpoints return all results in one response. The exceptions:

  • Serial logs (GET /compute/:id/serial-logs) use a cursor: boot_id, offset, direction (older/newer), and limit (default 200, max 1000).
  • Bucket object listing follows S3 semantics (max-keys, marker/continuation-token).

If you hit a list endpoint where pagination would matter and there’s no cursor today, — we’ll add it.

Versioning

APIs are additive-only within a major version. Breaking changes ship behind a new path prefix (e.g. /v2/…). Today only Object Storage uses an explicit /v1/ prefix because of the S3-compatible surface; the rest are at the root and are considered v1 implicitly.

Field additions, new optional query parameters, and new endpoints are not breaking. Removing a field or changing its type is.

Rate limiting

There is no published per-account rate limit today. We reserve the right to throttle abusive clients with 429 Too Many Requests. Retry with exponential backoff; the response includes a Retry-After header when set.

Webhooks

Two webhook receivers exist today, both consumed internally:

  • IAM accepts WhatsApp delivery webhooks (/webhook/whatsapp).
  • Billing accepts Razorpay payment webhooks (/webhooks/razorpay).

Outbound webhooks (Excloud → your endpoint) are not exposed yet.

Per-service docs

ServiceConcept docsSwagger
ComputeConcept guidecompute.excloud.in/docs
Object StorageConcept guidebuckets.excloud.in/docs
SecretsConcept guidesecrets.excloud.in/docs
KubernetesConcept guidek8sapi.excloud.in/docs
DNSConcept guidedns.excloud.in/docs
DatabaseConcept guidedatabase.excloud.in/docs
IAMPolicies, Permissionsiam.excloud.in/docs