15 min read

REST API Reference

Full REST API documentation covering authentication, core resource endpoints, webhooks, and SDKs.

APIRESTOAuth2WebhooksSDK
01

Base URL and versioning

All API requests are made over HTTPS to the versioned base URL. Breaking changes are introduced in a new version; the current stable version is v1.

Base URL
https://api.bluewhalestack.com/v1
Note: BYOC and Sovereign customers have a private API endpoint inside their deployment network. Your account team will provide the correct base URL.

The API version is set in the path (e.g., /v1/inventory/resources). We recommend pinning the version in your integration code rather than using a versionless alias.

02

Authentication

The API uses OAuth 2.0 client credentials flow. Create a service credential in Settings → API → Service credentials, then exchange it for a short-lived bearer token.

  1. 1

    Create a service credential

    Settings → API → Service credentials → Create credential. Give it a descriptive name and select the scopes you need (read:inventory, write:provisioning, etc.). Copy the client_id and client_secret — the secret is shown only once.

  2. 2

    Request an access token

    Exchange your credentials for a bearer token at the token endpoint. Tokens are valid for 1 hour.

    curl -X POST https://api.bluewhalestack.com/oauth/token \
      -H "Content-Type: application/json" \
      -d '{
        "grant_type": "client_credentials",
        "client_id":  "<CLIENT_ID>",
        "client_secret": "<CLIENT_SECRET>",
        "scope": "read:inventory write:provisioning"
      }'
    
    # Response
    {
      "access_token": "eyJhbGciOiJSUzI1Ni...",
      "token_type": "Bearer",
      "expires_in": 3600,
      "scope": "read:inventory write:provisioning"
    }
  3. 3

    Use the token

    Include the token in the Authorization header for every API request.

    curl https://api.bluewhalestack.com/v1/inventory/resources \
      -H "Authorization: Bearer <ACCESS_TOKEN>"
03

Rate limits

Rate limits are applied per service credential and per organisation. Exceeding the limit returns a 429 Too Many Requests response with a Retry-After header.

  • Standard edition: 120 requests / minute per credential
  • Enterprise edition: 600 requests / minute per credential
  • Telco & Datacenter / Government editions: negotiated limits
  • Bulk read endpoints (/v1/inventory/resources with pagination) are excluded from per-minute limits and have separate daily quotas
Rate limit response headers
X-RateLimit-Limit:     120
X-RateLimit-Remaining: 87
X-RateLimit-Reset:     1718000460   # Unix timestamp when the window resets
Retry-After:           12           # Seconds to wait (only on 429)
04

Core endpoints

Inventory

List resources
# List all resources (paginated)
GET /v1/inventory/resources
  ?provider=aws          # Filter by cloud: aws | azure | gcp | oracle | alibaba | huawei
  &type=ec2_instance     # Filter by resource type
  &region=ap-southeast-1 # Filter by region
  &page=1                # Page number (default: 1)
  &per_page=100          # Results per page (max: 500)

# Response
{
  "data": [
    {
      "id":       "res_01J9...",
      "type":     "ec2_instance",
      "provider": "aws",
      "region":   "ap-southeast-1",
      "name":     "web-prod-01",
      "status":   "running",
      "tags":     { "env": "prod", "team": "platform" },
      "metadata": { "instance_type": "t3.medium", "image_id": "ami-..." },
      "discovered_at": "2026-06-22T04:00:00Z"
    }
  ],
  "meta": { "total": 1247, "page": 1, "per_page": 100 }
}
Get a single resource
GET /v1/inventory/resources/:id

# Response includes full metadata and available lifecycle actions
{
  "id": "res_01J9...",
  "type": "ec2_instance",
  ...
  "actions": ["start", "stop", "reboot", "terminate"]
}

Provisioning

Submit a provisioning request
POST /v1/catalog/requests
Content-Type: application/json

{
  "resource_type": "ec2_instance",
  "cloud_account_id": "acct_01J8...",
  "region": "ap-southeast-1",
  "name": "api-staging-01",
  "environment": "staging",
  "config": {
    "instance_type": "t3.medium",
    "ami_id": "ami-0df7a207adb9748c7",
    "vpc_id": "vpc-0abc...",
    "subnet_id": "subnet-0def...",
    "key_name": "my-keypair"
  },
  "tags": { "env": "staging", "team": "backend", "project": "api-v2" }
}

# Response
{
  "request_id": "req_01JA...",
  "status": "pending_approval",
  "estimated_monthly_cost_usd": 28.50
}

Events

List platform events (audit log)
GET /v1/events
  ?from=2026-06-01T00:00:00Z
  &to=2026-06-22T23:59:59Z
  &actor=user@example.com
  &resource_id=res_01J9...
  &action=resource.terminated

# Response
{
  "data": [
    {
      "id":          "evt_01JB...",
      "action":      "resource.terminated",
      "actor":       { "type": "user", "email": "ops@example.com" },
      "resource_id": "res_01J9...",
      "timestamp":   "2026-06-22T10:15:32Z",
      "metadata":    { "reason": "decommission", "ticket": "INC-4821" }
    }
  ]
}
05

Webhooks

Webhooks push real-time events to your endpoint as HTTP POST requests. Register webhook endpoints in Settings → API → Webhooks.

  • resource.discovered — new resource found during a discovery poll
  • resource.changed — resource state or metadata changed
  • resource.terminated — resource deleted or terminated
  • request.submitted — new provisioning request created
  • request.approved — provisioning request approved
  • request.rejected — provisioning request rejected
  • request.completed — provisioned resource is live
  • connector.error — a cloud connector poll failed
Example webhook payload
{
  "id":        "wh_01JC...",
  "event":     "resource.discovered",
  "timestamp": "2026-06-22T04:03:11Z",
  "data": {
    "resource_id": "res_01JD...",
    "type":        "s3_bucket",
    "provider":    "aws",
    "region":      "ap-southeast-1",
    "name":        "my-new-bucket"
  },
  "signature": "sha256=abc123..."
}
Tip: Verify the webhook signature using the shared secret shown at registration. The signature is computed as HMAC-SHA256(body, secret) and included in the X-BWS-Signature header.
06

SDKs and CLI

Official SDKs for Python and Go are in beta. A CLI is available for common automation tasks.

Python SDK (beta)
pip install bluewhale-stack

from bluewhale import Client

client = Client(
    client_id="<CLIENT_ID>",
    client_secret="<CLIENT_SECRET>",
)

# List all running EC2 instances
resources = client.inventory.list(
    provider="aws",
    type="ec2_instance",
    filters={"status": "running"},
)
for r in resources:
    print(r.name, r.region, r.metadata["instance_type"])
CLI
# Install
curl -sSL https://get.bluewhalestack.com/cli | bash

# Authenticate
bws auth login --client-id <ID> --client-secret <SECRET>

# List resources
bws inventory list --provider aws --type ec2_instance

# Submit a provisioning request from a YAML spec
bws catalog request --file request.yaml
Note: SDK and CLI documentation is currently in preview. Request full access and the Go SDK via your account team or the contact form.
07

Error codes

All errors return a JSON body with a code, message, and optional details array.

Error response shape
{
  "error": {
    "code":    "RESOURCE_NOT_FOUND",
    "message": "The resource with ID res_01J9... was not found.",
    "details": [],
    "request_id": "req-trace-abc123"
  }
}
  • 400 INVALID_REQUEST — request body is malformed or missing required fields
  • 401 UNAUTHORIZED — missing or invalid bearer token
  • 403 FORBIDDEN — token does not have the required scope for this operation
  • 404 RESOURCE_NOT_FOUND — the specified resource or entity does not exist
  • 409 CONFLICT — the request conflicts with existing state (e.g., duplicate name)
  • 422 VALIDATION_ERROR — request is syntactically valid but fails business rules
  • 429 RATE_LIMITED — too many requests; check the Retry-After header
  • 500 INTERNAL_ERROR — unexpected server error; reference the request_id when contacting support

Have a question or hit a blocker?

Our support team and account engineers are here to help.

Contact support