API reference

Cloud connections

Read-only links to your cloud provider accounts' billing.

More about this resource

A cloud connection gives Pleaxy read-only access to one cloud provider account's billing, through access you create in your own account with a setup script. AWS uses a cross-account IAM role, Google Cloud Workload Identity Federation and Azure a federated credential, each for short-lived sessions with no long-lived key stored. Oracle Cloud uses an API signing key Pleaxy generates for the connection; you upload only its public key. Connecting is two calls: init returns the values the setup script needs, then CreateCloudConnection verifies the access and completes the connection. Only the person who started a setup can complete or cancel it.

List cloud connections

Lists the workspace's cloud connections.

GET/v1/workspaces/{regionId}/cloud-connections

Returns

200 OK with the object shown in the response.

More details

Lists the workspace's cloud connections, including setups still in progress (status pending). Never returns secrets or the identifiers the setup used (role ARN, external ID, service account, OCIDs, tenant or app IDs).

Response fields

  • dataSourcesArray<"invoices" | "current_cost">

    What Pleaxy may read: finalized invoices and/or month-to-date cost. Absent means both.

  • lastSyncStatus"ok" | "error" | "throttled" | "never"

    How the last billing sync went. lastSyncErrorCode says why one failed: throttled, access_revoked, platform_config, data_not_enabled or unknown.

Errors

  • 401 Unauthorized - No credential was presented, or the Bearer token / X-Api-Key value is missing, invalid, expired, or revoked.
  • 403 Forbidden - The caller's Bearer token or API key doesn't grant access to this workspace (regionId), or lacks the required role.
GET /v1/workspaces/{regionId}/cloud-connections
Request
curl "$PLEAXY_API_BASE_URL/v1/workspaces/{regionId}/cloud-connections" \
  -H "X-Api-Key: $PLEAXY_API_KEY"
Response · 200 OK
[
   {
      "id": "string",
      "provider": "aws" | "gcp" | "azure" | "oci",
      "accountLabel": "string",
      "detail": "string",
      "spend": number,
      "status": "connected" | "pending" | "error",
      "connectedAt": "string",
      "awsAccountId": "string",
      "dataSources": [ "invoices" | "current_cost" ],
      "gcp": { "billingAccountId": "string", "providerId": "string" },
      "oci": { "homeRegion": "string", "keyFingerprint": "string" },
      "azure": { "scopeDisplayName": "string", "agreementType": "string" },
      "lastSyncedAt": "string",
      "lastSyncStatus": "ok" | "error" | "throttled" | "never",
      "lastSyncError": "string",
      "lastSyncErrorCode": "throttled" | "access_revoked" | "platform_config" | "data_not_enabled" | "unknown"
   }
]

Init AWS cloud connection

Starts connecting an AWS account.

POST/v1/workspaces/{regionId}/cloud-connections/aws/init

Returns

201 Created with the object shown in the response.

More details

Starts connecting an AWS account and returns the values to give the setup script (CloudFormation, CDK or CLI), which creates a read-only IAM role in your account. Calling it again returns your own unfinished setup, with the same external ID. Takes no body.

Response fields

  • connectionIdstring

    Pass it to CreateCloudConnection as awsConnectionId.

  • cloudFormationTemplateUrlstring

    Absent when this deployment publishes no CloudFormation template; use the CDK or CLI script then.

Errors

  • 401 Unauthorized - No credential was presented, or the Bearer token / X-Api-Key value is missing, invalid, expired, or revoked.
  • 403 Forbidden - The caller's Bearer token or API key doesn't grant access to this workspace (regionId), or lacks the required role.
POST /v1/workspaces/{regionId}/cloud-connections/aws/init
Request
curl -X POST "$PLEAXY_API_BASE_URL/v1/workspaces/{regionId}/cloud-connections/aws/init" \
  -H "X-Api-Key: $PLEAXY_API_KEY"
Response · 201 Created
{
   "connectionId": "string",
   "platformAwsAccountId": "string",
   "externalId": "string",
   "cloudFormationTemplateUrl": "string"
}

Init cloud connection

Starts connecting a Google Cloud, Azure or Oracle Cloud account.

POST/v1/workspaces/{regionId}/cloud-connections/{provider}/init

Parameters

  • provider"gcp" | "azure" | "oci"Required

    The provider to connect.

Returns

201 Created with the object shown in the response.

More details

The same as InitAwsCloudConnection for Google Cloud, Azure or Oracle Cloud: returns the per-connection values that provider's setup script pins, including a connectionId to pass to CreateCloudConnection (as gcpConnectionId, azureConnectionId or ociConnectionId). Calling it again returns your own unfinished setup. Takes no body.

Response fields

  • gcpobject

    connectionId, platformAwsAccountId, federationRoleArn, expectedSubject, poolId and providerId: the Workload Identity Federation values the setup script pins.

  • azureobject

    connectionId, issuer, subject, audience, appDisplayName and credentialName: the federated credential the setup script creates on your app.

  • ociobject

    connectionId, publicKeyPem, fingerprint and regions: the public key to upload to the pleaxy-billing user, and the home regions to choose from.

Errors

  • 404 Not Found - This provider's live connector isn't switched on in this deployment ("Real connections to this provider aren't switched on.").
  • 401 Unauthorized - No credential was presented, or the Bearer token / X-Api-Key value is missing, invalid, expired, or revoked.
  • 403 Forbidden - The caller's Bearer token or API key doesn't grant access to this workspace (regionId), or lacks the required role.
POST /v1/workspaces/{regionId}/cloud-connections/{provider}/init
Request
curl -X POST "$PLEAXY_API_BASE_URL/v1/workspaces/{regionId}/cloud-connections/{provider}/init" \
  -H "X-Api-Key: $PLEAXY_API_KEY"
Response · 201 Created
{
   "connectionId": "string",
   ...the provider's setup values
}

Discover azure billing scopes

Lists the Azure billing profiles you can connect.

POST/v1/workspaces/{regionId}/cloud-connections/azure/discover

Body

  • azureConnectionIdstringRequired

    connectionId from InitCloudConnection.

  • azureTenantIdstringRequired

    The Microsoft Entra tenant the app was registered in (GUID).

  • azureClientIdstringRequired

    The app registration's Application (client) ID (GUID).

  • azureBillingAccountIdstringRequired

    The Microsoft Customer Agreement billing account ID (<guid>:<guid>_YYYY-MM-DD).

  • azureBillingProfileIdstringRequired

    The billing profile ID the app has Billing profile reader on.

Returns

201 Created with the object shown in the response.

More details

Azure only, between init and CreateCloudConnection: proves the tenant ID and app (client) ID the setup script printed, and reads the Microsoft Customer Agreement billing account and billing profile you name, so you can pick the profile to connect. Only the person who started the setup may call it, and it counts against the same attempt limit and cooldown as CreateCloudConnection.

Errors

  • 404 Not Found - Azure's live connector isn't switched on, or the setup is gone or was started by someone else.
  • 429 Too Many Requests - Tried again too soon; retryAfterSeconds says when.
  • 401 Unauthorized - No credential was presented, or the Bearer token / X-Api-Key value is missing, invalid, expired, or revoked.
  • 403 Forbidden - The caller's Bearer token or API key doesn't grant access to this workspace (regionId), or lacks the required role.
POST /v1/workspaces/{regionId}/cloud-connections/azure/discover
Request
curl -X POST "$PLEAXY_API_BASE_URL/v1/workspaces/{regionId}/cloud-connections/azure/discover" \
  -H "X-Api-Key: $PLEAXY_API_KEY"
Response · 201 Created
{
   "scopes": [
      { "billingAccountId": "string", "billingProfileId": "string", "displayName": "string", "billingAccountDisplayName": "string", "agreementType": "string" }
   ]
}

Create cloud connection

Finishes connecting a cloud account.

POST/v1/workspaces/{regionId}/cloud-connections

Body

  • provider"aws" | "gcp" | "azure" | "oci"Required

    The cloud provider to connect.

  • accountLabelstringRequired

    Your label for this account, e.g. "Production payer".

  • dataSourcesArray<"invoices" | "current_cost">

    What Pleaxy may read: finalized invoices and/or month-to-date cost. Omitted: both. Pleaxy never calls the provider for a source you leave out, including on a manual sync. Some providers charge per request for current cost (AWS Cost Explorer).

  • supplierContactEmailstring

    Optional contact at the provider for the supplier entry this creates.

  • awsConnectionIdstring

    AWS, required: connectionId from InitAwsCloudConnection.

  • roleArnstring

    AWS, required: the IAM role the setup script created, arn:aws:iam::<12-digit account>:role/<name>.

  • gcpConnectionIdstring

    Google Cloud: connectionId from InitCloudConnection.

  • gcpProjectNumberstring

    Google Cloud: the billing export project's number (digits).

  • gcpServiceAccountEmailstring

    Google Cloud: the service account the setup script created in that project.

  • gcpExportTablestring

    Google Cloud: the standard usage cost export table, project.dataset.gcp_billing_export_v1_XXXXXX_XXXXXX_XXXXXX.

  • azureConnectionIdstring

    Azure: connectionId from InitCloudConnection.

  • azureBillingAccountIdstring

    Azure: the billing account of the profile picked with DiscoverAzureBillingScopes.

  • azureBillingProfileIdstring

    Azure: the billing profile picked with DiscoverAzureBillingScopes.

  • ociConnectionIdstring

    Oracle Cloud: connectionId from InitCloudConnection.

  • ociTenancyOcidstring

    Oracle Cloud: the tenancy OCID (ocid1.tenancy.oc1..…).

  • ociUserOcidstring

    Oracle Cloud: the OCID of the pleaxy-billing user the setup script created.

  • ociHomeRegionstring

    Oracle Cloud: the tenancy's home region, one of those InitCloudConnection lists.

  • detailstring

    Only for a demo connection, where a provider's live connector is switched off: an account identifier you type. A live connection reads it from the provider instead.

Returns

201 Created with the object shown in the response.

More details

Completes a setup started with init: Pleaxy checks it can read your billing with the access the setup script created, then marks the connection connected and adds the provider to your suppliers. Send the fields for your provider. Only the person who started the setup may complete it. Gated by the region's plan: the Free plan allows one connected provider.

Errors

  • 400 Bad Request - Validation failed; Pleaxy couldn't read billing with the access given (the code says which provider, e.g. CLOUD_VERIFY_FAILED); too many failed attempts for this setup, so start again with init (code ending ATTEMPTS_EXHAUSTED); or the region's plan has reached its connected-provider limit (Free: 1).
  • 404 Not Found - The setup is gone, expired, or was started by someone else.
  • 409 Conflict - This setup, or the same billing account or scope, is already connected.
  • 429 Too Many Requests - Tried again too soon after a failed attempt; retryAfterSeconds says when.
  • 401 Unauthorized - No credential was presented, or the Bearer token / X-Api-Key value is missing, invalid, expired, or revoked.
  • 403 Forbidden - The caller's Bearer token or API key doesn't grant access to this workspace (regionId), or lacks the required role.
POST /v1/workspaces/{regionId}/cloud-connections
Request
curl -X POST "$PLEAXY_API_BASE_URL/v1/workspaces/{regionId}/cloud-connections" \
  -H "X-Api-Key: $PLEAXY_API_KEY" \
  -H "Content-Type: application/json" \
  -d @body.json
body.json
{
   "provider": "aws",
   "accountLabel": "string",
   "awsConnectionId": "string",
   "roleArn": "string",
   "dataSources": [ "invoices", "current_cost" ]
}
Response · 201 Created
{
   "id": "string",
   "provider": "aws" | "gcp" | "azure" | "oci",
   "accountLabel": "string",
   "detail": "string",
   "spend": number,
   "status": "connected" | "pending" | "error",
   "connectedAt": "string",
   "awsAccountId": "string",
   "dataSources": [ "invoices" | "current_cost" ],
   "gcp": { "billingAccountId": "string", "providerId": "string" },
   "oci": { "homeRegion": "string", "keyFingerprint": "string" },
   "azure": { "scopeDisplayName": "string", "agreementType": "string" },
   "lastSyncedAt": "string",
   "lastSyncStatus": "ok" | "error" | "throttled" | "never",
   "lastSyncError": "string",
   "lastSyncErrorCode": "throttled" | "access_revoked" | "platform_config" | "data_not_enabled" | "unknown"
}

Sync cloud connection

Syncs a cloud account's billing data now.

POST/v1/workspaces/{regionId}/cloud-connections/{id}/sync

Parameters

  • idstringRequired

    The cloud connection id.

Returns

201 Created with the object shown in the response.

More details

Syncs one connected account's billing data now, reading only the connection's dataSources. Once every 15 minutes per connection. Takes no body.

Errors

  • 400 Bad Request - Synced less than 15 minutes ago ("…try again in {n}m."), or the connection isn't a connected account with a live billing connector.
  • 404 Not Found - No such connection in the workspace, or it was disconnected.
  • 401 Unauthorized - No credential was presented, or the Bearer token / X-Api-Key value is missing, invalid, expired, or revoked.
  • 403 Forbidden - The caller's Bearer token or API key doesn't grant access to this workspace (regionId), or lacks the required role.
POST /v1/workspaces/{regionId}/cloud-connections/{id}/sync
Request
curl -X POST "$PLEAXY_API_BASE_URL/v1/workspaces/{regionId}/cloud-connections/{id}/sync" \
  -H "X-Api-Key: $PLEAXY_API_KEY"
Response · 201 Created
{
   "id": "string",
   "provider": "aws" | "gcp" | "azure" | "oci",
   "accountLabel": "string",
   "detail": "string",
   "spend": number,
   "status": "connected" | "pending" | "error",
   "connectedAt": "string",
   "awsAccountId": "string",
   "dataSources": [ "invoices" | "current_cost" ],
   "gcp": { "billingAccountId": "string", "providerId": "string" },
   "oci": { "homeRegion": "string", "keyFingerprint": "string" },
   "azure": { "scopeDisplayName": "string", "agreementType": "string" },
   "lastSyncedAt": "string",
   "lastSyncStatus": "ok" | "error" | "throttled" | "never",
   "lastSyncError": "string",
   "lastSyncErrorCode": "throttled" | "access_revoked" | "platform_config" | "data_not_enabled" | "unknown"
}

Disconnect cloud connection

Disconnects a cloud account.

DELETE/v1/workspaces/{regionId}/cloud-connections/{id}

Parameters

  • idstringRequired

    The cloud connection id.

Returns

200 OK with the object shown in the response.

More details

Disconnects a cloud account, or cancels a setup in progress. Deletes the connection with everything Pleaxy stored for it (for Oracle Cloud, its encrypted API key) and records who disconnected it. For Oracle Cloud the response names the key fingerprint to delete from user pleaxy-billing. Remove the access in your own account too.

Signed-in session with 'edit' access to suppliers; an API key gets 403. A setup in progress can only be cancelled by the person who started it.

Errors

  • 403 Forbidden - The caller is an API key, lacks 'edit' on suppliers, or is cancelling someone else's setup ("Only the person who started this setup can cancel it.").
  • 404 Not Found - No such connection in the workspace.
  • 401 Unauthorized - No credential was presented, or the Bearer token / X-Api-Key value is missing, invalid, expired, or revoked.
DELETE /v1/workspaces/{regionId}/cloud-connections/{id}
Request
curl -X DELETE "$PLEAXY_API_BASE_URL/v1/workspaces/{regionId}/cloud-connections/{id}" \
  -H "X-Api-Key: $PLEAXY_API_KEY"
Response · 200 OK
{
   "id": "string",
   "provider": "aws" | "gcp" | "azure" | "oci",
   "ociKeyFingerprint": "string"
}

Add cloud provider as supplier

Adds a cloud provider as a supplier without connecting an account.

POST/v1/workspaces/{regionId}/cloud-connections/{provider}/supplier

Parameters

  • provider"aws" | "gcp" | "azure" | "oci"Required

    The provider to add.

Returns

201 Created with the object shown in the response.

More details

Adds a cloud provider to your suppliers list without connecting an account, so you can raise POs to it. Nothing is read from the provider. Returns the provider's existing supplier entry if there is one, and connecting later links to the same entry. Needs 'create' access to suppliers. Takes no body.

Errors

  • 404 Not Found - Unknown provider.
  • 409 Conflict - Code SUPPLIER_ALREADY_LISTED: a supplier with that name already has an onboarding under way or approved.
  • 401 Unauthorized - No credential was presented, or the Bearer token / X-Api-Key value is missing, invalid, expired, or revoked.
  • 403 Forbidden - The caller's Bearer token or API key doesn't grant access to this workspace (regionId), or lacks the required role.
POST /v1/workspaces/{regionId}/cloud-connections/{provider}/supplier
Request
curl -X POST "$PLEAXY_API_BASE_URL/v1/workspaces/{regionId}/cloud-connections/{provider}/supplier" \
  -H "X-Api-Key: $PLEAXY_API_KEY"
Response · 201 Created
{
   "id": "string",
   "buyerOrgId": "string",
   "supplierName": "string",
   "cloudProvider": "aws" | "gcp" | "azure" | "oci",
   "status": "pending_invite" | "invited" | "in_progress" | "submitted" | "approved" | "rejected",
   "createdAt": "string"
}
Talk to us