# Causely documentation: api > Full content of the "api" section of the Causely documentation. This file contains all documentation content in a single document following the llmstxt.org standard. ## API Authentication All Causely GraphQL API requests require authentication using a Bearer token. You'll need to exchange your API client credentials for an access token using our authentication endpoint. ### How to Get API Access Token To verify that your credentials are working, you can use the following curl command. Replace `` and `` with the credentials you generated above: ```bash CAUSELY_CLIENT_ID= CAUSELY_CLIENT_SECRET= curl -X POST https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token \ -H "Content-Type: application/json" \ -d "{ \"clientId\": \"${CAUSELY_CLIENT_ID}\", \"secret\": \"${CAUSELY_CLIENT_SECRET}\" }" ``` **Example Response:** ```json { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik...", "refresh_token": "25b14169-b912-4d15-8f9c-xxxxxxxx", "expires_in": 86400, "expires": "Sat, 31 May 2025 22:54:23 GMT" } ``` You can use the `access_token` for subsequent API calls. If you want to retrieve the access token and store it in an environment variable, you can use the following curl command: ```bash CAUSELY_CLIENT_ID= CAUSELY_CLIENT_SECRET= export CAUSELY_ACCESS_TOKEN=$(response=$(curl -s -w "\n%{http_code}" -X POST https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token \ -H "Content-Type: application/json" \ -d "{\"clientId\": \"${CAUSELY_CLIENT_ID}\", \"secret\": \"${CAUSELY_CLIENT_SECRET}\"}"); \ http_code=$(echo "$response" | tail -n1); \ body=$(echo "$response" | sed '$d'); \ if [ "$http_code" = "200" ]; then echo "$body" | jq -r .access_token; else echo "$body" >&2; false; fi) ``` You can then use the `${CAUSELY_ACCESS_TOKEN}` environment variable for subsequent API calls. Similarly you can obtain the token using your preferred programming language. **python** ```python # Make sure to install the requests library: pip install requests import os, requests def get_causely_access_token(client_id, client_secret, url="https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token"): res = requests.post(url, headers={"Content-Type": "application/json"}, json={"clientId": client_id, "secret": client_secret}) if res.status_code != 200: raise requests.HTTPError(f"Token request failed ({res.status_code}): {res.text}") token = res.json().get("access_token") if not token: raise ValueError("No access_token in response.") return token # Example usage: if __name__ == "__main__": cid, secret = os.getenv("CAUSELY_CLIENT_ID"), os.getenv("CAUSELY_CLIENT_SECRET") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET.") try: token = get_causely_access_token(cid, secret) print("Access token:", token) except Exception as e: print(f"Error: {e}") ``` **javascript** ```javascript const https = require('https'); function getCauselyAccessToken( clientId, clientSecret, url = 'https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token', ) { return new Promise((resolve, reject) => { const data = JSON.stringify({ clientId, secret: clientSecret }); const req = https.request( url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data), }, }, (res) => { let body = ''; res.on('data', (chunk) => (body += chunk)); res.on('end', () => { if (res.statusCode !== 200) { return reject(new Error(`HTTP ${res.statusCode}: ${body}`)); } const json = JSON.parse(body); if (!json.access_token) return reject(new Error('No access_token in response.')); resolve(json.access_token); }); }, ); req.on('error', reject); req.write(data); req.end(); }); } // Example usage const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET) { console.error('Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET'); process.exit(1); } getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET) .then((token) => console.log('Access token:', token)) .catch((err) => console.error('Error:', err.message)); ``` **go** ```go package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" "os" ) func getToken(id, secret, url string) (string, error) { data, _ := json.Marshal(map[string]string{"clientId": id, "secret": secret}) req, _ := http.NewRequest("POST", url, bytes.NewReader(data)) req.Header.Set("Content-Type", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { return "", err } defer res.Body.Close() body, _ := io.ReadAll(res.Body) if res.StatusCode != 200 { return "", fmt.Errorf("status %d: %s", res.StatusCode, body) } var resp map[string]interface{} if err := json.Unmarshal(body, &resp); err != nil { return "", err } token, ok := resp["access_token"].(string) if !ok || token == "" { return "", fmt.Errorf("no access_token in response") } return token, nil } func main() { id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET") if id == "" || secret == "" { fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") os.Exit(1) } url := "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token" token, err := getToken(id, secret, url) if err != nil { fmt.Fprintln(os.Stderr, "Error:", err) os.Exit(1) } fmt.Println("Access token:", token) } ``` --- ## Gateway Token Management Gateway tokens authenticate the Causely mediator agent when it connects to the Causely platform. Creating tokens via the REST API enables automated deployment pipelines, for example ArgoCD or Backstage workflows that provision a mediator without manual steps in the UI. :::tip Prerequisite You need a valid Bearer access token before calling this endpoint. See [Authentication](/api/authentication) for how to obtain one. ::: ### Create a Gateway Token **`POST https://api.causely.app/api/tokens`** **bash** ```bash CAUSELY_CLIENT_ID= CAUSELY_CLIENT_SECRET= TOKEN_NAME= # Obtain a Bearer access token export CAUSELY_ACCESS_TOKEN=$(response=$(curl -s -w "\n%{http_code}" -X POST https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token \ -H "Content-Type: application/json" \ -d "{\"clientId\": \"${CAUSELY_CLIENT_ID}\", \"secret\": \"${CAUSELY_CLIENT_SECRET}\"}"); \ http_code=$(echo "$response" | tail -n1); \ body=$(echo "$response" | sed '$d'); \ if [ "$http_code" = "200" ]; then echo "$body" | jq -r .access_token; else echo "$body" >&2; false; fi) # Create a gateway token curl -s -X POST https://api.causely.app/api/tokens \ -H "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"name\": \"${TOKEN_NAME}\"}" ``` **python** ```python # Make sure to install the requests library: pip install requests import os, requests def create_gateway_token(access_token, name, url="https://api.causely.app/api/tokens"): res = requests.post( url, headers={ "Authorization": f"Bearer {access_token}", "Content-Type": "application/json", }, json={"name": name}, ) if res.status_code != 201: raise requests.HTTPError(f"Token creation failed ({res.status_code}): {res.text}") return res.json() # Example usage: if __name__ == "__main__": cid = os.getenv("CAUSELY_CLIENT_ID") secret = os.getenv("CAUSELY_CLIENT_SECRET") token_name = os.getenv("TOKEN_NAME", "my-mediator-token") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET.") access_token = get_causely_access_token(cid, secret) gateway_token = create_gateway_token(access_token, token_name) print("Gateway token value:", gateway_token["tokenValue"]) ``` **javascript** ```javascript const https = require('https'); function createGatewayToken(accessToken, name, url = 'https://api.causely.app/api/tokens') { return new Promise((resolve, reject) => { const data = JSON.stringify({ name }); const parsedUrl = new URL(url); const req = https.request( { hostname: parsedUrl.hostname, path: parsedUrl.pathname, method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data), }, }, (res) => { let body = ''; res.on('data', (chunk) => (body += chunk)); res.on('end', () => { if (res.statusCode !== 201) { return reject(new Error(`HTTP ${res.statusCode}: ${body}`)); } resolve(JSON.parse(body)); }); }, ); req.on('error', reject); req.write(data); req.end(); }); } // Example usage const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; const tokenName = process.env.TOKEN_NAME || 'my-mediator-token'; if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET) { console.error('Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET'); process.exit(1); } (async () => { try { const accessToken = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const gatewayToken = await createGatewayToken(accessToken, tokenName); console.log('Gateway token value:', gatewayToken.tokenValue); } catch (err) { console.error('Error:', err.message); process.exit(1); } })(); ``` **go** ```go package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" "os" ) type GatewayToken struct { ID string `json:"id"` Name string `json:"name"` TokenValue string `json:"tokenValue"` MediatorID string `json:"mediatorId"` ProjectID string `json:"projectId"` CreatedBy string `json:"createdBy"` CreatedByEmail string `json:"createdByEmail"` State string `json:"state"` CreatedAt string `json:"createdAt"` } func createGatewayToken(accessToken, name, url string) (*GatewayToken, error) { data, _ := json.Marshal(map[string]string{"name": name}) req, _ := http.NewRequest("POST", url, bytes.NewReader(data)) req.Header.Set("Authorization", "Bearer "+accessToken) req.Header.Set("Content-Type", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer res.Body.Close() body, _ := io.ReadAll(res.Body) if res.StatusCode != 201 { return nil, fmt.Errorf("status %d: %s", res.StatusCode, body) } var token GatewayToken if err := json.Unmarshal(body, &token); err != nil { return nil, err } return &token, nil } func main() { id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET") tokenName := os.Getenv("TOKEN_NAME") if id == "" || secret == "" { fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") os.Exit(1) } if tokenName == "" { tokenName = "my-mediator-token" } accessToken, err := getToken(id, secret, "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token") if err != nil { fmt.Fprintln(os.Stderr, "Error getting access token:", err) os.Exit(1) } gatewayToken, err := createGatewayToken(accessToken, tokenName, "https://api.causely.app/api/tokens") if err != nil { fmt.Fprintln(os.Stderr, "Error creating gateway token:", err) os.Exit(1) } fmt.Println("Gateway token value:", gatewayToken.TokenValue) } ``` **Example Response (201 Created):** ```json { "id": "c2679064-c908-4bb0-9928-a0e3ce37da80", "name": "my-mediator-token", "tokenValue": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "mediatorId": "beb09338-3c0b-43ab-9b34-6a3fa496abf4", "projectId": "4877d57d-6789-4838-af52-7fe9af353c9e", "createdBy": "8df4696c-fffd-43c9-8df6-c80921471efb", "createdByEmail": "user@example.com", "state": "active", "createdAt": "2026-05-26T19:16:45Z" } ``` | Field | Description | |---|---| | `id` | Unique identifier for this token record | | `name` | The name you provided | | `tokenValue` | The token secret. Use this as `mediator.gateway.token` in Helm, `mediator.secretName` with a Kubernetes secret, or `CAUSELY_GATEWAY_TOKEN` in Docker/Nomad deployments | | `mediatorId` | ID of the mediator this token is associated with | | `projectId` | ID of the project this token belongs to | | `createdBy` | User ID of the token creator | | `createdByEmail` | Email of the token creator | | `state` | Token status (`active`) | | `createdAt` | ISO 8601 creation timestamp | :::note Using `tokenValue` in deployments The `tokenValue` from the response is the gateway token referenced throughout the [installation docs](/installation). For example: ```bash # Helm --set mediator.gateway.token="${TOKEN_VALUE}" # Docker CAUSELY_GATEWAY_TOKEN="${TOKEN_VALUE}" ``` For Kubernetes deployments, you can store the token in a secret instead of specifying it in Helm values. This is recommended for production and GitOps workflows. See [Using a Kubernetes Secret for the Access Token](/installation/customize#using-a-kubernetes-secret-for-the-access-token) for setup instructions. ::: ### List Gateway Tokens **`GET https://api.causely.app/api/tokens`** Returns all gateway tokens for the project, including both active and revoked tokens. **bash** ```bash curl -s -X GET https://api.causely.app/api/tokens \ -H "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" ``` **python** ```python import requests def list_gateway_tokens(access_token, url="https://api.causely.app/api/tokens"): res = requests.get( url, headers={"Authorization": f"Bearer {access_token}"}, ) if res.status_code != 200: raise requests.HTTPError(f"List tokens failed ({res.status_code}): {res.text}") return res.json() # Example usage: if __name__ == "__main__": import os cid = os.getenv("CAUSELY_CLIENT_ID") secret = os.getenv("CAUSELY_CLIENT_SECRET") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET.") access_token = get_causely_access_token(cid, secret) tokens = list_gateway_tokens(access_token) for token in tokens: print(f"{token['name']} ({token['state']}): {token['id']}") ``` **javascript** ```javascript const https = require('https'); function listGatewayTokens(accessToken, url = 'https://api.causely.app/api/tokens') { return new Promise((resolve, reject) => { const parsedUrl = new URL(url); const req = https.request( { hostname: parsedUrl.hostname, path: parsedUrl.pathname, method: 'GET', headers: { Authorization: `Bearer ${accessToken}`, }, }, (res) => { let body = ''; res.on('data', (chunk) => (body += chunk)); res.on('end', () => { if (res.statusCode !== 200) { return reject(new Error(`HTTP ${res.statusCode}: ${body}`)); } resolve(JSON.parse(body)); }); }, ); req.on('error', reject); req.end(); }); } // Example usage const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET) { console.error('Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET'); process.exit(1); } (async () => { try { const accessToken = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const tokens = await listGatewayTokens(accessToken); tokens.forEach((t) => console.log(`${t.name} (${t.state}): ${t.id}`)); } catch (err) { console.error('Error:', err.message); process.exit(1); } })(); ``` **go** ```go func listGatewayTokens(accessToken, url string) ([]GatewayToken, error) { req, _ := http.NewRequest("GET", url, nil) req.Header.Set("Authorization", "Bearer "+accessToken) res, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer res.Body.Close() body, _ := io.ReadAll(res.Body) if res.StatusCode != 200 { return nil, fmt.Errorf("status %d: %s", res.StatusCode, body) } var tokens []GatewayToken if err := json.Unmarshal(body, &tokens); err != nil { return nil, err } return tokens, nil } ``` **Example Response (200 OK):** ```json [ { "id": "afce85cb-70b4-4624-8198-d38843a7ccc0", "name": "my-mediator-token", "tokenValue": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "mediatorId": "beb09338-3c0b-43ba-9b34-6a3fa496abf4", "projectId": "4877d57d-6789-4838-af52-7fe9af353c9e", "createdBy": "8df4696c-fffd-43c9-8df6-c80921471efb", "createdByEmail": "user@example.com", "state": "active", "createdAt": "2026-06-03T22:11:39Z" }, { "id": "5152a4b0-327b-46f5-8926-5716bbdd2bed", "name": "old-mediator-token", "mediatorId": "beb09338-3c0b-43ba-9b34-6a3fa496abf4", "projectId": "4877d57d-6789-4838-af52-7fe9af353c9e", "createdBy": "f67341c8-12cf-49bc-b9c7-09f44885750c", "createdByEmail": "user@example.com", "state": "revoked", "revokedAt": "2026-05-26T21:36:29Z", "revokedBy": "8df4696c-fffd-43c9-8df6-c80921471efb", "createdAt": "2026-05-26T21:24:11Z" } ] ``` The response is an array of token objects. Each object contains the same fields as the [create response](#create-a-gateway-token). Revoked tokens include additional fields: | Field | Description | |---|---| | `id` | Unique identifier for this token record | | `name` | The name assigned to the token | | `tokenValue` | The token secret. Only present on active tokens | | `mediatorId` | ID of the mediator this token is associated with | | `projectId` | ID of the project this token belongs to | | `createdBy` | User ID of the token creator | | `createdByEmail` | Email of the token creator | | `state` | Token status: `active` or `revoked` | | `createdAt` | ISO 8601 creation timestamp | | `revokedAt` | ISO 8601 timestamp of when the token was revoked (revoked tokens only) | | `revokedBy` | User ID of who performed the revocation (revoked tokens only) | ### Revoke a Gateway Token **`POST https://api.causely.app/api/tokens/{tokenId}/revoke?tokenId={tokenId}`** Revoking a token immediately deactivates it. The mediator using that token will lose connectivity to the platform. **bash** ```bash TOKEN_ID= curl -s -X POST "https://api.causely.app/api/tokens/${TOKEN_ID}/revoke?tokenId=${TOKEN_ID}" \ -H "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" ``` **python** ```python import requests def revoke_gateway_token(access_token, token_id, base_url="https://api.causely.app/api/tokens"): url = f"{base_url}/{token_id}/revoke" res = requests.post( url, params={"tokenId": token_id}, headers={"Authorization": f"Bearer {access_token}"}, ) if res.status_code != 200: raise requests.HTTPError(f"Token revocation failed ({res.status_code}): {res.text}") return res.json() # Example usage: if __name__ == "__main__": import os cid = os.getenv("CAUSELY_CLIENT_ID") secret = os.getenv("CAUSELY_CLIENT_SECRET") token_id = os.getenv("TOKEN_ID") if not cid or not secret or not token_id: raise EnvironmentError("Missing CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET, or TOKEN_ID.") access_token = get_causely_access_token(cid, secret) result = revoke_gateway_token(access_token, token_id) print("Token state:", result["state"]) ``` **javascript** ```javascript const https = require('https'); function revokeGatewayToken(accessToken, tokenId, baseUrl = 'https://api.causely.app/api/tokens') { return new Promise((resolve, reject) => { const url = new URL(`${baseUrl}/${tokenId}/revoke`); url.searchParams.set('tokenId', tokenId); const req = https.request( { hostname: url.hostname, path: url.pathname + url.search, method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, }, }, (res) => { let body = ''; res.on('data', (chunk) => (body += chunk)); res.on('end', () => { if (res.statusCode !== 200) { return reject(new Error(`HTTP ${res.statusCode}: ${body}`)); } resolve(JSON.parse(body)); }); }, ); req.on('error', reject); req.end(); }); } // Example usage const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET, TOKEN_ID } = process.env; if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET || !TOKEN_ID) { console.error('Missing CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET, or TOKEN_ID'); process.exit(1); } (async () => { try { const accessToken = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const result = await revokeGatewayToken(accessToken, TOKEN_ID); console.log('Token state:', result.state); } catch (err) { console.error('Error:', err.message); process.exit(1); } })(); ``` **go** ```go func revokeGatewayToken(accessToken, tokenID, baseURL string) (*GatewayToken, error) { url := fmt.Sprintf("%s/%s/revoke?tokenId=%s", baseURL, tokenID, tokenID) req, _ := http.NewRequest("POST", url, nil) req.Header.Set("Authorization", "Bearer "+accessToken) res, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer res.Body.Close() body, _ := io.ReadAll(res.Body) if res.StatusCode != 200 { return nil, fmt.Errorf("status %d: %s", res.StatusCode, body) } var token GatewayToken if err := json.Unmarshal(body, &token); err != nil { return nil, err } return &token, nil } ``` **Example Response (200 OK):** ```json { "id": "8323a17c-f6f5-4a7a-b04e-481790314b03", "name": "my-mediator-token", "mediatorId": "beb09338-3c0b-43ba-9b34-6a3fa496abf4", "projectId": "4877d57d-6789-4838-af52-7fe9af353c9e", "createdBy": "8df4696c-fffd-43c9-8df6-c80921471efb", "createdByEmail": "user@example.com", "state": "revoked", "revokedAt": "2026-05-26T19:42:26Z", "revokedBy": "8df4696c-fffd-43c9-8df6-c80921471efb", "createdAt": "2026-05-26T19:42:09Z" } ``` | Field | Description | |---|---| | `state` | `revoked` once the token has been invalidated | | `revokedAt` | ISO 8601 timestamp of when the token was revoked | | `revokedBy` | User ID of who performed the revocation | --- ## Setting Up GraphQL Clients To maximize efficiency and code reusability when integrating with the Causely GraphQL API, we recommend setting up proper GraphQL client libraries rather than using raw HTTP requests. This approach provides better error handling, type safety, query validation, and cleaner code that can be reused across multiple API operations. ### Install GraphQL Client Libraries Install the recommended GraphQL client libraries for your programming language to enable robust API integration with automatic query validation and enhanced developer experience: **python** ```bash pip install gql[all] requests ``` **javascript** ```bash npm install @apollo/client graphql ``` **bash** ```bash # Install gq (GraphQL CLI tool) curl -sSL https://github.com/houseabsolute/gq/releases/latest/download/gq-Linux-x86_64.tar.gz | tar xz # Or use your package manager, e.g., brew install gq ``` **go** ```bash go get github.com/machinebox/graphql ``` ### Create Reusable GraphQL Client Functions Implement these language-specific GraphQL client functions that integrate seamlessly with the authentication methods from the previous section. These functions provide a clean, reusable interface for executing any GraphQL query against the Causely API: **python** ```python from gql import gql, Client from gql.transport.requests import RequestsHTTPTransport def create_graphql_client(access_token): """Create a GraphQL client with authentication.""" transport = RequestsHTTPTransport( url="https://api.causely.app/query/", headers={"Authorization": f"Bearer {access_token}"} ) return Client(transport=transport, fetch_schema_from_transport=True) def post_query(client, query_string, variables=None): """Execute a GraphQL query using the client.""" query = gql(query_string) return client.execute(query, variable_values=variables) # Usage example: # client = create_graphql_client(get_causely_access_token(client_id, secret)) # result = post_query(client, query_string, variables) ``` **javascript** ```javascript const { ApolloClient, InMemoryCache, createHttpLink, gql } = require('@apollo/client'); function createGraphQLClient(accessToken) { const httpLink = createHttpLink({ uri: 'https://api.causely.app/query/', headers: { Authorization: `Bearer ${accessToken}`, }, }); return new ApolloClient({ link: httpLink, cache: new InMemoryCache(), }); } async function postQuery(client, queryString, variables = {}) { const result = await client.query({ query: gql(queryString), variables, fetchPolicy: 'no-cache', }); return result.data; } // Usage example: // const client = createGraphQLClient(await getCauselyAccessToken(clientId, secret)); // const result = await postQuery(client, queryString, variables); ``` **bash** ```bash # Function to execute GraphQL queries using gq post_query() { local query_file="$1" local variables_file="$2" gq https://api.causely.app/query/ \ --header "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" \ --query-file "$query_file" \ --variables-file "$variables_file" } # Alternative using curl with GraphQL post_query_curl() { local query="$1" local variables="$2" curl -X POST https://api.causely.app/query/ \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" \ -d "{\"query\": \"$query\", \"variables\": $variables}" } ``` **go** ```go package main import ( "context" "github.com/machinebox/graphql" ) func createGraphQLClient(accessToken string) *graphql.Client { client := graphql.NewClient("https://api.causely.app/query/") client.WithHTTPHeader("Authorization", "Bearer "+accessToken) return client } func postQuery(client *graphql.Client, queryString string, variables map[string]interface{}) (interface{}, error) { req := graphql.NewRequest(queryString) // Add variables to the request for key, value := range variables { req.Var(key, value) } var response interface{} err := client.Run(context.Background(), req, &response) return response, err } // Usage example: // client := createGraphQLClient(token) // result, err := postQuery(client, queryString, variables) ``` --- ## API Reference Guide The Causely API enables developers to integrate Diagnosis capabilities into their applications and workflows. This comprehensive guide provides step-by-step examples for authentication, querying defects, and automating incident response using the Causely platform. ### Getting Started with Causely API #### Create API Client Credentials Before you can use the Causely API, you need to generate API client credentials (Client ID and Secret) from the Causely platform: 1. **Login to Causely:** - Go to [Causely Portal](https://portal.causely.app/) - Login with your credentials 2. **Navigate to Personal Tokens:** - Click on the Profile Icon in the top-right corner - Select "Admin Portal" - Choose "Personal Tokens" 3. **Generate Token:** - Click "Generate Token" - Provide a description and expiration date - Click "Create" 4. **Save Credentials:** - Record your Client ID and Secret Key in a safe place - You'll use these credentials in the examples below ### Next Steps Once you have your API credentials, you can proceed with: - **[Authentication](/api/authentication)** - Learn how to authenticate with the Causely GraphQL API - **[Gateway Tokens](/api/gateway-tokens)** - Create and manage gateway tokens for mediator deployment - **[GraphQL Clients](/api/graphql-clients)** - Set up reusable GraphQL client libraries - **[Query Examples](/api/queries/getting-started)** - Explore example queries and mutations ### API Support For technical questions about the Causely GraphQL API, [contact our support team](mailto:support@causely.io) for assistance with integration challenges. --- ## Query Defects and Root Causes This query example demonstrates how to retrieve the first 20 high-severity, active defects and Diagnoses from the Causely platform using the GraphQL utilities defined above. :::note Terminology GraphQL uses **Defect** for the underlying root-cause type (`defectConnection`, `Defect`). In product and MCP docs, the same concept is called a **Diagnosis**. Multiple Diagnoses can group under an **Issue**, the incident-level view exposed by MCP `get_issues` and GraphQL `issues()`. Use this page for GraphQL clients querying defect instances directly; use MCP `get_issues` for incident triage prompts. ::: :::note The START_TIME is set to the current time in UTC. You may need to adjust the timestamp to your needs. ::: :::tip Prerequisite This example reuses the helper utilities defined in the [Authentication](/api/authentication) and [GraphQL Clients](/api/graphql-clients) sections: fetching an access token, creating the GraphQL client, and sending a request with the `post_query` wrapper (CLI, Python, or Go). Keep those helpers in scope before running this query. ::: **python** ```python import os from datetime import datetime, timezone if __name__ == "__main__": # Get credentials from environment cid, secret = os.getenv("CAUSELY_CLIENT_ID"), os.getenv("CAUSELY_CLIENT_SECRET") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") # Get access token and create GraphQL client token = get_causely_access_token(cid, secret) client = create_graphql_client(token) # Prepare query variables start_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S") + ".000+00:00" variables = { "defectFilter": { "state": "ACTIVE", "severities": ["Critical", "High"], "startTime": start_time, "scopesFilter": {"scopes": []}, "entityTypes": [], "defectNames": [], "entityName": "" }, "groupRecurring": True, "first": 20 } # Execute the query query = """ fragment LabelFragment on Label { key value __typename } fragment BasicEntityWithLabelsFragment on Entity { id name typeName labels { ...LabelFragment __typename } __typename } fragment DefectFragment on Defect { id name fromTime toTime remediated serviceCount entityId entityType entity { ...BasicEntityWithLabelsFragment __typename } activeCount missingCount severity __typename } fragment DefectRelatedOccurrencesFragment on Defect { relatedOccurrrences { id name fromTime toTime entity { id name typeName __typename } severity __typename } __typename } fragment BasicEntityFragment on Entity { id name typeName __typename } fragment SymptomFragmentWithoutLabels on Symptom { id name active state entityId entityType fromTime toTime isPropagated entity { ...BasicEntityFragment __typename } __typename } fragment EventFragmentWithoutLabels on Event { id name active time entity { ...BasicEntityFragment __typename } __typename } query defectConnection($defectFilter: DefectFilter, $groupRecurring: Boolean, $first: Int, $after: String, $last: Int, $before: String) { defectConnection(defectFilter: $defectFilter groupRecurring: $groupRecurring first: $first after: $after last: $last before: $before) { totalCount edges { node { ...DefectFragment ...DefectRelatedOccurrencesFragment symptoms { ...SymptomFragmentWithoutLabels __typename } events { ...EventFragmentWithoutLabels __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } } """ result = post_query(client, query, variables) print(result) ``` **javascript** ```javascript const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET) { console.error('Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET'); process.exit(1); } (async () => { try { // Get access token and create GraphQL client const token = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const client = createGraphQLClient(token); // Prepare query variables const startTime = new Date().toISOString().replace(/\.\d+Z$/, '.000+00:00'); const variables = { defectFilter: { state: 'ACTIVE', severities: ['Critical', 'High'], startTime, scopesFilter: { scopes: [] }, entityTypes: [], defectNames: [], entityName: '', }, groupRecurring: true, first: 20, }; // Execute the query const query = ` fragment LabelFragment on Label { key value __typename } fragment BasicEntityWithLabelsFragment on Entity { id name typeName labels { ...LabelFragment __typename } __typename } fragment DefectFragment on Defect { id name fromTime toTime remediated serviceCount entityId entityType entity { ...BasicEntityWithLabelsFragment __typename } activeCount missingCount severity __typename } fragment DefectRelatedOccurrencesFragment on Defect { relatedOccurrrences { id name fromTime toTime entity { id name typeName __typename } severity __typename } __typename } fragment BasicEntityFragment on Entity { id name typeName __typename } fragment SymptomFragmentWithoutLabels on Symptom { id name active state entityId entityType fromTime toTime isPropagated entity { ...BasicEntityFragment __typename } __typename } fragment EventFragmentWithoutLabels on Event { id name active time entity { ...BasicEntityFragment __typename } __typename } query defectConnection($defectFilter: DefectFilter, $groupRecurring: Boolean, $first: Int, $after: String, $last: Int, $before: String) { defectConnection(defectFilter: $defectFilter groupRecurring: $groupRecurring first: $first after: $after last: $last before: $before) { totalCount edges { node { ...DefectFragment ...DefectRelatedOccurrencesFragment symptoms { ...SymptomFragmentWithoutLabels __typename } events { ...EventFragmentWithoutLabels __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } } `; const result = await postQuery(client, query, variables); console.log(JSON.stringify(result, null, 2)); } catch (err) { console.error('Error:', err.message); process.exit(1); } })(); ``` **bash** ```bash # Set up credentials and get token export CAUSELY_CLIENT_ID= export CAUSELY_CLIENT_SECRET= export CAUSELY_ACCESS_TOKEN=$(response=$(curl -s -w "\n%{http_code}" -X POST https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token \ -H "Content-Type: application/json" \ -d "{\"clientId\": \"${CAUSELY_CLIENT_ID}\", \"secret\": \"${CAUSELY_CLIENT_SECRET}\"}"); \ http_code=$(echo "$response" | tail -n1); \ body=$(echo "$response" | sed '$d'); \ if [ "$http_code" = "200" ]; then echo "$body" | jq -r .access_token; else echo "$body" >&2; false; fi) # Create query and variables files cat > defect_query.graphql << 'EOF' fragment LabelFragment on Label { key value __typename } fragment BasicEntityWithLabelsFragment on Entity { id name typeName labels { ...LabelFragment __typename } __typename } fragment DefectFragment on Defect { id name fromTime toTime remediated serviceCount entityId entityType entity { ...BasicEntityWithLabelsFragment __typename } activeCount missingCount severity __typename } fragment DefectRelatedOccurrencesFragment on Defect { relatedOccurrrences { id name fromTime toTime entity { id name typeName __typename } severity __typename } __typename } fragment BasicEntityFragment on Entity { id name typeName __typename } fragment SymptomFragmentWithoutLabels on Symptom { id name active state entityId entityType fromTime toTime isPropagated entity { ...BasicEntityFragment __typename } __typename } fragment EventFragmentWithoutLabels on Event { id name active time entity { ...BasicEntityFragment __typename } __typename } query defectConnection($defectFilter: DefectFilter, $groupRecurring: Boolean, $first: Int, $after: String, $last: Int, $before: String) { defectConnection(defectFilter: $defectFilter groupRecurring: $groupRecurring first: $first after: $after last: $last before: $before) { totalCount edges { node { ...DefectFragment ...DefectRelatedOccurrencesFragment symptoms { ...SymptomFragmentWithoutLabels __typename } events { ...EventFragmentWithoutLabels __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } } EOF START_TIME="$(TZ=UTC date +%Y-%m-%dT%H:%M:%S).000+00:00" cat > variables.json << EOF { "defectFilter": { "state": "ACTIVE", "severities": ["Critical", "High"], "startTime": "${START_TIME}", "scopesFilter": {"scopes": []}, "entityTypes": [], "defectNames": [], "entityName": "" }, "groupRecurring": true, "first": 20 } EOF # Execute the query using gq (if available) or curl if command -v gq &> /dev/null; then post_query "defect_query.graphql" "variables.json" else query=$(cat defect_query.graphql | tr '\n' ' ') variables=$(cat variables.json) post_query_curl "$query" "$variables" fi # Clean up temporary files rm -f defect_query.graphql variables.json ``` **go** ```go package main import ( "fmt" "os" "time" ) func main() { // Get credentials from environment id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET") if id == "" || secret == "" { fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") os.Exit(1) } // Get access token and create GraphQL client token, err := getToken(id, secret, "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token") if err != nil { fmt.Fprintln(os.Stderr, "Error getting token:", err) os.Exit(1) } client := createGraphQLClient(token) // Prepare query variables startTime := time.Now().UTC().Format("2006-01-02T15:04:05") + ".000+00:00" variables := map[string]interface{}{ "defectFilter": map[string]interface{}{ "state": "ACTIVE", "severities": []string{"Critical", "High"}, "startTime": startTime, "scopesFilter": map[string]interface{}{"scopes": []string{}}, "entityTypes": []string{}, "defectNames": []string{}, "entityName": "", }, "groupRecurring": true, "first": 20, } // Execute the query query := `fragment LabelFragment on Label { key value __typename } fragment BasicEntityWithLabelsFragment on Entity { id name typeName labels { ...LabelFragment __typename } __typename } fragment DefectFragment on Defect { id name fromTime toTime remediated serviceCount entityId entityType entity { ...BasicEntityWithLabelsFragment __typename } activeCount missingCount severity __typename } fragment DefectRelatedOccurrencesFragment on Defect { relatedOccurrrences { id name fromTime toTime entity { id name typeName __typename } severity __typename } __typename } fragment BasicEntityFragment on Entity { id name typeName __typename } fragment SymptomFragmentWithoutLabels on Symptom { id name active state entityId entityType fromTime toTime isPropagated entity { ...BasicEntityFragment __typename } __typename } fragment EventFragmentWithoutLabels on Event { id name active time entity { ...BasicEntityFragment __typename } __typename } query defectConnection($defectFilter: DefectFilter, $groupRecurring: Boolean, $first: Int, $after: String, $last: Int, $before: String) { defectConnection(defectFilter: $defectFilter groupRecurring: $groupRecurring first: $first after: $after last: $last before: $before) { totalCount edges { node { ...DefectFragment ...DefectRelatedOccurrencesFragment symptoms { ...SymptomFragmentWithoutLabels __typename } events { ...EventFragmentWithoutLabels __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } }` result, err := postQuery(client, query, variables) if err != nil { fmt.Fprintln(os.Stderr, "Error running query:", err) os.Exit(1) } fmt.Println(result) } ``` **graphql** First, let's define the GraphQL query and variables: ```graphql fragment LabelFragment on Label { key value __typename } fragment BasicEntityWithLabelsFragment on Entity { id name typeName labels { ...LabelFragment __typename } __typename } fragment DefectFragment on Defect { id name fromTime toTime remediated serviceCount entityId entityType entity { ...BasicEntityWithLabelsFragment __typename } activeCount missingCount severity __typename } fragment DefectRelatedOccurrencesFragment on Defect { relatedOccurrrences { id name fromTime toTime entity { id name typeName __typename } severity __typename } __typename } fragment BasicEntityFragment on Entity { id name typeName __typename } fragment SymptomFragmentWithoutLabels on Symptom { id name active state entityId entityType fromTime toTime isPropagated entity { ...BasicEntityFragment __typename } __typename } fragment EventFragmentWithoutLabels on Event { id name active time entity { ...BasicEntityFragment __typename } __typename } query defectConnection( $defectFilter: DefectFilter $groupRecurring: Boolean $first: Int $after: String $last: Int $before: String ) { defectConnection( defectFilter: $defectFilter groupRecurring: $groupRecurring first: $first after: $after last: $last before: $before ) { totalCount edges { node { ...DefectFragment ...DefectRelatedOccurrencesFragment symptoms { ...SymptomFragmentWithoutLabels __typename } events { ...EventFragmentWithoutLabels __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } } ``` --- ## Get User Scopes This query retrieves user scopes and access permissions for the authenticated user. User scopes define which resources and data the current user can access within the Causely platform. :::tip Prerequisite This example reuses the helper utilities defined in the [Authentication](/api/authentication) and [GraphQL Clients](/api/graphql-clients) sections—fetching an access token, creating the GraphQL client, and sending a request with the `post_query` wrapper (CLI, Python, or Go). Keep those helpers in scope before running this query. ::: **python** ```python import os if __name__ == "__main__": # Get credentials from environment cid, secret = os.getenv("CAUSELY_CLIENT_ID"), os.getenv("CAUSELY_CLIENT_SECRET") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") # Get access token and create GraphQL client token = get_causely_access_token(cid, secret) client = create_graphql_client(token) # Prepare query variables variables = { "filter": { "nameExpr": "" } } # Execute the query query = """ query getUserScopes($filter: UserScopeFilter, $first: Int, $after: String, $last: Int, $before: String) { getUserScopes( filter: $filter first: $first after: $after last: $last before: $before ) { totalCount edges { node { id name audience ownerId lastUpdate scopes { typeName typeValues __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } } """ result = post_query(client, query, variables) print(result) ``` **javascript** ```javascript const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET) { console.error('Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET'); process.exit(1); } (async () => { try { // Get access token and create GraphQL client const token = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const client = createGraphQLClient(token); // Prepare query variables const variables = { filter: { nameExpr: '', }, }; // Execute the query const query = ` query getUserScopes($filter: UserScopeFilter, $first: Int, $after: String, $last: Int, $before: String) { getUserScopes( filter: $filter first: $first after: $after last: $last before: $before ) { totalCount edges { node { id name audience ownerId lastUpdate scopes { typeName typeValues __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } } `; const result = await postQuery(client, query, variables); console.log(JSON.stringify(result, null, 2)); } catch (err) { console.error('Error:', err.message); process.exit(1); } })(); ``` **bash** ```bash # Set up credentials and get token export CAUSELY_CLIENT_ID= export CAUSELY_CLIENT_SECRET= export CAUSELY_ACCESS_TOKEN=$(response=$(curl -s -w "\n%{http_code}" -X POST https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token \ -H "Content-Type: application/json" \ -d "{\"clientId\": \"${CAUSELY_CLIENT_ID}\", \"secret\": \"${CAUSELY_CLIENT_SECRET}\"}"); \ http_code=$(echo "$response" | tail -n1); \ body=$(echo "$response" | sed '$d'); \ if [ "$http_code" = "200" ]; then echo "$body" | jq -r .access_token; else echo "$body" >&2; false; fi) # Create query and variables files cat > user_scopes_query.graphql << 'EOF' query getUserScopes($filter: UserScopeFilter, $first: Int, $after: String, $last: Int, $before: String) { getUserScopes( filter: $filter first: $first after: $after last: $last before: $before ) { totalCount edges { node { id name audience ownerId lastUpdate scopes { typeName typeValues __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } } EOF cat > user_scopes_variables.json << EOF { "filter": { "nameExpr": "" } } EOF # Execute the query using gq (if available) or curl if command -v gq &> /dev/null; then post_query "user_scopes_query.graphql" "user_scopes_variables.json" else query=$(cat user_scopes_query.graphql | tr '\n' ' ') variables=$(cat user_scopes_variables.json) post_query_curl "$query" "$variables" fi # Clean up temporary files rm -f user_scopes_query.graphql user_scopes_variables.json ``` **go** ```go package main import ( "fmt" "os" ) func main() { // Get credentials from environment id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET") if id == "" || secret == "" { fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") os.Exit(1) } // Get access token and create GraphQL client token, err := getToken(id, secret, "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token") if err != nil { fmt.Fprintln(os.Stderr, "Error getting token:", err) os.Exit(1) } client := createGraphQLClient(token) // Prepare query variables variables := map[string]interface{}{ "filter": map[string]interface{}{ "nameExpr": "", }, } // Execute the query query := `query getUserScopes($filter: UserScopeFilter, $first: Int, $after: String, $last: Int, $before: String) { getUserScopes( filter: $filter first: $first after: $after last: $last before: $before ) { totalCount edges { node { id name audience ownerId lastUpdate scopes { typeName typeValues __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } }` result, err := postQuery(client, query, variables) if err != nil { fmt.Fprintln(os.Stderr, "Error running query:", err) os.Exit(1) } fmt.Println(result) } ``` **graphql** ```graphql query getUserScopes($filter: UserScopeFilter, $first: Int, $after: String, $last: Int, $before: String) { getUserScopes(filter: $filter, first: $first, after: $after, last: $last, before: $before) { totalCount edges { node { id name audience ownerId lastUpdate scopes { typeName typeValues __typename } __typename } cursor __typename } pageInfo { hasNextPage hasPreviousPage startCursor endCursor totalCount __typename } __typename } } ``` **Variables:** ```json { "filter": { "nameExpr": "" } } ``` --- ## Hiding Root Causes You may want to hide a root cause for a time period if you are not planning on addressing it immediately or if you are performing maintenance and the behavior is expected. The recommended way to hide a specific root cause is to use **Entity Configs** of type `IgnoreRC`. To avoid overwriting existing configuration for that entity, you should: 1. Query the current `IgnoreRC` config for the entity. 2. Merge your new rule with any existing entries. 3. Call the `CreateEntityConfigs` mutation with the combined config. :::tip Prerequisite Each example below reuses the helper utilities defined in the [Authentication](/api/authentication) and [GraphQL Clients](/api/graphql-clients) sections (`get_causely_access_token`, `create_graphql_client`, `post_query`, and their language equivalents). ::: **python** ```python import os import json # Reuse helpers defined earlier in this guide: # - get_causely_access_token # - create_graphql_client # - post_query GET_CONFIGS_QUERY = """ query GetEntityConfigs($entityId: String!, $configType: String!) { entityConfigs(entityId: $entityId, configType: $configType) { entityId type data } } """ CREATE_CONFIGS_MUTATION = """ mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } """ def load_existing_ignore_rc_configs(client, entity_id, config_type="IgnoreRC"): """Fetch existing IgnoreRC configs and return them as a Python list.""" variables = {"entityId": entity_id, "configType": config_type} result = post_query(client, GET_CONFIGS_QUERY, variables) entries = [] for cfg in result.get("entityConfigs", []): data_str = cfg.get("data") or "[]" try: entries.extend(json.loads(data_str)) except json.JSONDecodeError: # If data is malformed, skip rather than failing the whole operation continue return entries def save_ignore_rc_configs(client, entity_id, configs, config_type="IgnoreRC"): """Persist the merged IgnoreRC configs back to Causely.""" variables = { "entityConfigs": [{ "entityId": entity_id, "type": config_type, # If your schema uses ENUMs, pass the enum instead "data": json.dumps(configs), # Must be a JSON string }] } return post_query(client, CREATE_CONFIGS_MUTATION, variables) if __name__ == "__main__": # Get credentials from environment cid, secret = os.getenv("CAUSELY_CLIENT_ID"), os.getenv("CAUSELY_CLIENT_SECRET") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") # Get access token and create GraphQL client token = get_causely_access_token(cid, secret) client = create_graphql_client(token) # Target entity and root cause name you want to hide # Replace these example values with your actual entity ID and root cause name entity_id = "47c29d23-9f57-5d47-9f91-a72815edc8cf" defect_name_to_hide = "Malfunction" # 1) Load existing IgnoreRC configuration (if any) existing_configs = load_existing_ignore_rc_configs(client, entity_id) # 2) Add or update the entry for this root cause without losing existing ones new_entry = { "DefectName": defect_name_to_hide, # Set an appropriate expiry time for the ignore rule "UntilTime": "2025-11-15T10:51:00-04:00", } # Avoid adding duplicate entries for the same defect name merged_configs = [ cfg for cfg in existing_configs if cfg.get("DefectName") != defect_name_to_hide ] merged_configs.append(new_entry) # 3) Save the merged configuration back using the mutation result = save_ignore_rc_configs(client, entity_id, merged_configs) print(json.dumps(result, indent=2)) ``` **javascript** ```javascript // Reuses helpers defined earlier in this guide: // - getCauselyAccessToken // - createGraphQLClient // - postQuery (for queries) const { gql } = require('@apollo/client'); const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; const GET_CONFIGS_QUERY = ` query GetEntityConfigs($entityId: String!, $configType: String!) { entityConfigs(entityId: $entityId, configType: $configType) { entityId type data } } `; const CREATE_CONFIGS_MUTATION = ` mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } `; async function loadExistingIgnoreRcConfigs(client, entityId, configType = 'IgnoreRC') { const variables = { entityId, configType }; const data = await postQuery(client, GET_CONFIGS_QUERY, variables); const entries = []; for (const cfg of data.entityConfigs || []) { const dataStr = cfg.data || '[]'; try { entries.push(...JSON.parse(dataStr)); } catch { // Skip malformed data instead of failing the whole operation continue; } } return entries; } async function saveIgnoreRcConfigs(client, entityId, configs, configType = 'IgnoreRC') { const variables = { entityConfigs: [ { entityId, type: configType, // If your schema uses ENUMs, pass the enum instead data: JSON.stringify(configs), // Must be a JSON string }, ], }; const result = await client.mutate({ mutation: gql(CREATE_CONFIGS_MUTATION), variables, }); return result.data; } (async () => { if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET) { console.error('Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET'); process.exit(1); } // Get access token and create GraphQL client const token = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const client = createGraphQLClient(token); // Replace these example values with your actual entity ID and root cause name const entityId = '47c29d23-9f57-5d47-9f91-a72815edc8cf'; const defectNameToHide = 'Malfunction'; // 1) Load existing IgnoreRC configuration (if any) const existingConfigs = await loadExistingIgnoreRcConfigs(client, entityId); // 2) Add or update the entry for this root cause without losing existing ones const newEntry = { DefectName: defectNameToHide, // Set an appropriate expiry time for the ignore rule UntilTime: '2025-11-15T10:51:00-04:00', }; const mergedConfigs = existingConfigs.filter((cfg) => cfg.DefectName !== defectNameToHide); mergedConfigs.push(newEntry); // 3) Save the merged configuration back using the mutation const result = await saveIgnoreRcConfigs(client, entityId, mergedConfigs); console.log(JSON.stringify(result, null, 2)); })(); ``` **bash** ```bash #!/usr/bin/env bash set -euo pipefail # Prerequisites: # - CAUSELY_CLIENT_ID / CAUSELY_CLIENT_SECRET exported # - CAUSELY_ACCESS_TOKEN exported (see Authentication section) # - post_query / post_query_curl functions defined (see Bash GraphQL helpers section) # - jq installed # Replace these example values with your actual entity ID, root cause name and time ENTITY_ID="47c29d23-9f57-5d47-9f91-a72815edc8cf" DEFECT_NAME_TO_HIDE="Malfunction" UNTIL_TIME="2025-11-15T10:51:00-04:00" # 1) Define GraphQL query and mutation cat > get_entity_configs.graphql << 'EOF' query GetEntityConfigs($entityId: String!, $configType: String!) { entityConfigs(entityId: $entityId, configType: $configType) { entityId type data } } EOF cat > create_entity_configs.graphql << 'EOF' mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } EOF # 2) Query existing IgnoreRC config cat > get_entity_configs_variables.json << EOF { "entityId": "${ENTITY_ID}", "configType": "IgnoreRC" } EOF if command -v gq &> /dev/null; then RAW_RESPONSE=$(gq https://api.causely.app/query/ \ --header "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" \ --query-file get_entity_configs.graphql \ --variables-file get_entity_configs_variables.json) else QUERY=$(tr '\n' ' ' < get_entity_configs.graphql) VARIABLES=$(cat get_entity_configs_variables.json) RAW_RESPONSE=$(post_query_curl "$QUERY" "$VARIABLES") fi # 3) Extract current config entries (data is a JSON string) CURRENT_CONFIGS=$(echo "${RAW_RESPONSE}" \ | jq -r '.data.entityConfigs[0].data // "[]"' \ | jq -c 'try fromjson catch []') # 4) Merge in the new ignore rule (avoid duplicates on DefectName) MERGED_CONFIGS=$( jq -c --arg name "${DEFECT_NAME_TO_HIDE}" --arg until "${UNTIL_TIME}" ' (map(select(.DefectName != $name))) + [ { "DefectName": $name, "UntilTime": $until } ] ' <<< "${CURRENT_CONFIGS}" ) # 5) Build variables for CreateEntityConfigs (data must be a JSON string) DATA_STRING=$(jq -Rs . <<< "${MERGED_CONFIGS}") cat > create_entity_configs_variables.json << EOF { "entityConfigs": [ { "entityId": "${ENTITY_ID}", "type": "IgnoreRC", "data": ${DATA_STRING} } ] } EOF # 6) Call the mutation if command -v gq &> /dev/null; then gq https://api.causely.app/query/ \ --header "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" \ --query-file create_entity_configs.graphql \ --variables-file create_entity_configs_variables.json else MUTATION=$(tr '\n' ' ' < create_entity_configs.graphql) VARIABLES=$(cat create_entity_configs_variables.json) post_query_curl "$MUTATION" "$VARIABLES" fi # 7) Cleanup rm -f get_entity_configs.graphql create_entity_configs.graphql \ get_entity_configs_variables.json create_entity_configs_variables.json ``` **go** ```go package main import ( "encoding/json" "fmt" "os" ) // Reuse helpers defined earlier: // - getToken(id, secret, url) // - createGraphQLClient(accessToken string) *graphql.Client // - postQuery(client *graphql.Client, queryString string, variables map[string]interface{}) (interface{}, error) const getConfigsQuery = ` query GetEntityConfigs($entityId: String!, $configType: String!) { entityConfigs(entityId: $entityId, configType: $configType) { entityId type data } } ` const createConfigsMutation = ` mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } ` type entityConfigsResponse struct { EntityConfigs []struct { EntityID string `json:"entityId"` Type string `json:"type"` Data string `json:"data"` } `json:"entityConfigs"` } func loadExistingIgnoreRCConfigs(gqlClient *graphql.Client, entityID string, configType string) ([]map[string]interface{}, error) { variables := map[string]interface{}{ "entityId": entityID, "configType": configType, } raw, err := postQuery(gqlClient, getConfigsQuery, variables) if err != nil { return nil, err } // postQuery returns interface{}; marshal + unmarshal into a typed struct bytes, err := json.Marshal(raw) if err != nil { return nil, err } var wrapped struct { Data entityConfigsResponse `json:"data"` } if err := json.Unmarshal(bytes, &wrapped); err != nil { return nil, err } entries := []map[string]interface{}{} for _, cfg := range wrapped.Data.EntityConfigs { dataStr := cfg.Data if dataStr == "" { continue } var arr []map[string]interface{} if err := json.Unmarshal([]byte(dataStr), &arr); err != nil { // Skip malformed data instead of failing the whole operation continue } entries = append(entries, arr...) } return entries, nil } func saveIgnoreRCConfigs(gqlClient *graphql.Client, entityID string, configs []map[string]interface{}, configType string) (interface{}, error) { dataBytes, err := json.Marshal(configs) if err != nil { return nil, err } variables := map[string]interface{}{ "entityConfigs": []map[string]interface{}{ { "entityId": entityID, "type": configType, // If your schema uses ENUMs, pass the enum instead "data": string(dataBytes), // Must be a JSON string }, }, } return postQuery(gqlClient, createConfigsMutation, variables) } func main() { id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET") if id == "" || secret == "" { fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") os.Exit(1) } token, err := getToken(id, secret, "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token") if err != nil { fmt.Fprintln(os.Stderr, "Error getting token:", err) os.Exit(1) } client := createGraphQLClient(token) // Replace these example values with your actual entity ID, root cause name and time entityID := "47c29d23-9f57-5d47-9f91-a72815edc8cf" defectNameToHide := "Malfunction" untilTime := "2025-11-15T10:51:00-04:00" // 1) Load existing IgnoreRC configuration (if any) existing, err := loadExistingIgnoreRCConfigs(client, entityID, "IgnoreRC") if err != nil { fmt.Fprintln(os.Stderr, "Error loading configs:", err) os.Exit(1) } // 2) Add or update the entry for this root cause without losing existing ones merged := make([]map[string]interface{}, 0, len(existing)+1) for _, cfg := range existing { if name, ok := cfg["DefectName"].(string); ok && name == defectNameToHide { continue } merged = append(merged, cfg) } merged = append(merged, map[string]interface{}{ "DefectName": defectNameToHide, "UntilTime": untilTime, }) // 3) Save the merged configuration back using the mutation result, err := saveIgnoreRCConfigs(client, entityID, merged, "IgnoreRC") if err != nil { fmt.Fprintln(os.Stderr, "Error saving configs:", err) os.Exit(1) } out, _ := json.MarshalIndent(result, "", " ") fmt.Println(string(out)) } ``` **graphql** ```graphql # 1) Query existing IgnoreRC config for an entity query GetEntityConfigs($entityId: String!, $configType: String!) { entityConfigs(entityId: $entityId, configType: $configType) { entityId type data } } ``` **Variables:** ```json # Replace this example values with your actual entity ID. { "entityId": "47c29d23-9f57-5d47-9f91-a72815edc8cf", "configType": "IgnoreRC" } ``` The `data` field in the response is a **JSON string** that represents an array of ignore rules, for example: ```json [{ "DefectName": "SomeOtherDefect", "UntilTime": "2025-11-10T12:00:00-04:00" }] ``` You should: 1. Parse this JSON string in your client. 2. Remove any existing entries with the same `DefectName` you want to hide. 3. Append a new entry for the root cause you want to hide. 4. Stringify the merged array and send it back via `CreateEntityConfigs`. ```graphql # 2) Save merged IgnoreRC configuration mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } ``` **Variables (example after merging):** ```json # Replace this example values with your actual entity ID, root cause name and time { "entityConfigs": [ { "entityId": "47c29d23-9f57-5d47-9f91-a72815edc8cf", "type": "IgnoreRC", "data": "[{\"DefectName\":\"SomeOtherDefect\",\"UntilTime\":\"2025-11-10T12:00:00-04:00\"},{\"DefectName\":\"Malfunction\",\"UntilTime\":\"2025-11-15T10:51:00-04:00\"}]" } ] } ``` > Note: The `data` value must be a **JSON string**, not a nested JSON object. Most clients will use `JSON.stringify` or an equivalent function to produce this string. --- ## Testing Notification Payloads This example demonstrates how to **send a test notification** to Causely using a representative payload. It follows the same pattern as the examples above: reuse your token + GraphQL client helpers and then execute one mutation with a clear `variables` object. :::tip Prerequisite This example reuses the helper utilities defined in the [Authentication](/api/authentication) and [GraphQL Clients](/api/graphql-clients) sections—fetching an access token, creating the GraphQL client, and sending a request with the `post_query` wrapper (CLI, Python, or Go). Keep those helpers in scope before running this mutation. ::: **python** ```python import os import json if __name__ == "__main__": # Get credentials from environment cid, secret = os.getenv("CAUSELY_CLIENT_ID"), os.getenv("CAUSELY_CLIENT_SECRET") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") # Get access token and create GraphQL client token = get_causely_access_token(cid, secret) client = create_graphql_client(token) # Prepare mutation mutation = """ mutation createNotification($notification: NotificationInput!) { createNotification(notification: $notification) } """ # Build the payload embedded_payload = { "link": "https://portal.causely.app", "name": "Causely: Test Notification 42", "type": "ProblemDetected", # Options are ProblemDetected and ProblemCleared "entity": { "id": "22307647-43e6-5f08-a5e4-a3f50088ccec", "link": "https://portal.causely.app", "name": "payments-api", "type": "Node" }, "labels": { "k8s.cluster.name": "us-prod", # Test to route based on cluster "k8s.namespace.name": "payments", # Test to route based on name space "gcp.resource.zone": "https://www.gcp.com/compute/v1/projects/example-project/zones/us-central1-a", "causely.ai/cluster": "my-important-services-cluster" }, "objectId": "2ac21477-61f3-4ae0-9fc4-0c1ea43ff727", "severity": "High", # Options are Critical, High, Medium, Low "timestamp": "2025-09-14T19:15:16.410543344Z", "description": { "summary": "Sending test notification for entity in us-prod myApp1", "details": "Webhook Test" } } variables = { "notification": { "sourceId": "2f423693-5334-4586-a366-64d458535001", "type": 1, "payload": json.dumps(embedded_payload) } } result = post_query(client, mutation, variables) print(result) ``` **javascript** ```javascript // Reuses helpers defined above: getCauselyAccessToken, createGraphQLClient // Requires @apollo/client installed (as shown above) const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; const { gql } = require('@apollo/client'); if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET) { console.error('Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET'); process.exit(1); } (async () => { try { const token = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const client = createGraphQLClient(token); // Mutation matches working script exactly const mutation = ` mutation createNotification($notification: NotificationInput!) { createNotification(notification: $notification) } `; // Embedded payload (stringified below) const embeddedPayload = { link: 'https://portal.causely.app', name: 'Causely: Test Notification 42', type: 'ProblemDetected', // ProblemDetected | ProblemCleared entity: { id: '22307647-43e6-5f08-a5e4-a3f50088ccec', link: 'https://portal.causely.app', name: 'payments-api', type: 'Node', }, labels: { 'k8s.cluster.name': 'us-prod', 'k8s.namespace.name': 'payments', 'gcp.resource.zone': 'https://www.gcp.com/compute/v1/projects/example-project/zones/us-central1-a', 'causely.ai/cluster': 'my-important-services-cluster', }, objectId: '2ac21477-61f3-4ae0-9fc4-0c1ea43ff727', severity: 'High', // Critical | High | Medium | Low timestamp: '2025-09-14T19:15:16.410543344Z', description: { summary: 'Sending test notification for entity in us-prod myApp1', details: 'Webhook Test', }, }; const variables = { notification: { sourceId: '2f423693-5334-4586-a366-64d458535001', type: 1, payload: JSON.stringify(embeddedPayload), }, }; // Use mutate for a GraphQL mutation const result = await client.mutate({ mutation: gql(mutation), variables }); console.log(JSON.stringify(result.data, null, 2)); } catch (err) { console.error('Error:', err.message); process.exit(1); } })(); ``` **bash** ```bash # Assumes CAUSELY_ACCESS_TOKEN is already exported (see Authentication section) # Creates files for the mutation, an embedded payload JSON, and variables (with payload as a JSON string), then posts them. # 1) GraphQL mutation cat > create_notification.graphql << 'EOF' mutation createNotification($notification: NotificationInput!) { createNotification(notification: $notification) } EOF # 2) Embedded payload (domain JSON) cat > embedded_payload.json << 'EOF' { "link": "https://portal.causely.app", "name": "Causely: Test Notification 42", "type": "ProblemDetected", "entity": { "id": "22307647-43e6-5f08-a5e4-a3f50088ccec", "link": "https://portal.causely.app", "name": "payments-api", "type": "Node" }, "labels": { "k8s.cluster.name": "us-prod", "k8s.namespace.name": "payments", "gcp.resource.zone": "https://www.gcp.com/compute/v1/projects/example-project/zones/us-central1-a", "causely.ai/cluster": "my-important-services-cluster" }, "objectId": "2ac21477-61f3-4ae0-9fc4-0c1ea43ff727", "severity": "High", "timestamp": "2025-09-14T19:15:16.410543344Z", "description": { "summary": "Sending test notification for entity in us-prod myApp1", "details": "Webhook Test" } } EOF # 3) Build variables.json with payload as a *string* using jq to JSON-encode the file content PAYLOAD_STR=$(jq -Rs . < embedded_payload.json) cat > variables.json << EOF { "notification": { "sourceId": "2f423693-5334-4586-a366-64d458535001", "type": 1, "payload": ${PAYLOAD_STR} } } EOF # 4) Post using gq if available; otherwise curl if command -v gq &> /dev/null; then gq https://api.causely.app/query/ \ --header "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" \ --query-file create_notification.graphql \ --variables-file variables.json else curl -sS -X POST https://api.causely.app/query/ \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" \ -d "{\"query\":\"$(tr '\n' ' ' < create_notification.graphql)\",\"variables\":$(cat variables.json)}" fi # 5) Clean up rm -f create_notification.graphql embedded_payload.json variables.json ``` **go** ```go package main import ( "encoding/json" "fmt" "os" ) func main() { // Reuse helpers defined above: // getToken(id, secret, url) and createGraphQLClient(accessToken) id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET") if id == "" || secret == "" { fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") os.Exit(1) } token, err := getToken(id, secret, "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token") if err != nil { fmt.Fprintln(os.Stderr, "Error getting token:", err) os.Exit(1) } client := createGraphQLClient(token) // Mutation matches working script exactly mutation := ` mutation createNotification($notification: NotificationInput!) { createNotification(notification: $notification) } ` // Embedded payload (will be stringified) embeddedPayload := map[string]interface{}{ "link": "https://portal.causely.app", "name": "Causely: Test Notification 42", "type": "ProblemDetected", "entity": map[string]interface{}{ "id": "22307647-43e6-5f08-a5e4-a3f50088ccec", "link": "https://portal.causely.app", "name": "payments-api", "type": "Node", }, "labels": map[string]interface{}{ "k8s.cluster.name": "us-prod", "k8s.namespace.name": "payments", "gcp.resource.zone": "https://www.gcp.com/compute/v1/projects/example-project/zones/us-central1-a", "causely.ai/cluster": "my-important-services-cluster", }, "objectId": "2ac21477-61f3-4ae0-9fc4-0c1ea43ff727", "severity": "High", "timestamp": "2025-09-14T19:15:16.410543344Z", "description": map[string]interface{}{ "summary": "Sending test notification for entity in us-prod myApp1", "details": "Webhook Test", }, } payloadBytes, err := json.Marshal(embeddedPayload) if err != nil { fmt.Fprintln(os.Stderr, "Error marshaling payload:", err) os.Exit(1) } variables := map[string]interface{}{ "notification": map[string]interface{}{ "sourceId": "2f423693-5334-4586-a366-64d458535001", "type": 1, "payload": string(payloadBytes), // GraphQL expects a STRING here }, } result, err := postQuery(client, mutation, variables) if err != nil { fmt.Fprintln(os.Stderr, "Error running mutation:", err) os.Exit(1) } fmt.Println(result) } ``` **graphql** When sending a notification via GraphQL, the `payload` field must be passed as a **stringified JSON** (not as a nested JSON object). The embedded JSON represents the notification details and must be stringified before being sent in the GraphQL variables. Below is a clear breakdown: **Mutation:** ```graphql mutation createNotification($notification: NotificationInput!) { createNotification(notification: $notification) } ``` **Embedded Payload (JSON)** This is the JSON you want to send as the notification payload (before stringifying): ```json { "link": "https://portal.causely.app", "name": "Causely: Test Notification 42", "type": "ProblemDetected", "entity": { "id": "22307647-43e6-5f08-a5e4-a3f50088ccec", "link": "https://portal.causely.app", "name": "payments-api", "type": "Node" }, "labels": { "k8s.cluster.name": "us-prod", "k8s.namespace.name": "payments", "gcp.resource.zone": "https://www.gcp.com/compute/v1/projects/example-project/zones/us-central1-a", "causely.ai/cluster": "my-important-services-cluster" }, "objectId": "2ac21477-61f3-4ae0-9fc4-0c1ea43ff727", "severity": "High", "timestamp": "2025-09-14T19:15:16.410543344Z", "description": { "summary": "Sending test notification for entity in us-prod myApp1", "details": "Webhook Test" } } ``` **Variables (GraphQL input)** Notice that the `payload` value is the above JSON, stringified (escaped), and can be split across multiple lines for readability: ```json { "notification": { "sourceId": "2f423693-5334-4586-a366-64d458535001", "type": 1, "payload": "{\n \"link\": \"https://portal.causely.app\",\n \"name\": \"Causely: Test Notification 42\",\n \"type\": \"ProblemDetected\",\n \"entity\": {\n \"id\": \"22307647-43e6-5f08-a5e4-a3f50088ccec\",\n \"link\": \"https://portal.causely.app\",\n \"name\": \"payments-api\",\n \"type\": \"Node\"\n },\n \"labels\": {\n \"k8s.cluster.name\": \"us-prod\",\n \"k8s.namespace.name\": \"payments\",\n \"gcp.resource.zone\": \"https://www.gcp.com/compute/v1/projects/example-project/zones/us-central1-a\",\n \"causely.ai/cluster\": \"my-important-services-cluster\"\n },\n \"objectId\": \"2ac21477-61f3-4ae0-9fc4-0c1ea43ff727\",\n \"severity\": \"High\",\n \"timestamp\": \"2025-09-14T19:15:16.410543344Z\",\n \"description\": {\n \"summary\": \"Sending test notification for entity in us-prod myApp1\",\n \"details\": \"Webhook Test\"\n }\n}" } } ``` > **Note:** > The `payload` field must be a string. Most clients will use a function like `JSON.stringify()` to convert the embedded payload JSON into a string before passing it to the GraphQL mutation. > > This lets you clearly see how the original JSON maps into the string value required by the GraphQL API. --- ## Setting SLOs on HTTP Paths and RPC Methods You can set SLOs on **HTTP Paths** or **RPC Methods** that represent key endpoints for your application (for example, revenue-critical URIs or core RPC methods). Enabling SLOs on these entities configures SLO tracking for **both Request Duration and Request Error Rate**. When a Diagnosis impacts one of these endpoints and drives its SLO **at risk** or into **violation**, Causely treats that Diagnosis as **Urgent**. The recommended way to manage these SLOs is to use **Entity Configs** of type `EntityTier`. :::tip Prerequisite Each example below reuses the helper utilities defined in the [Authentication](/api/authentication) and [GraphQL Clients](/api/graphql-clients) sections (`get_causely_access_token`, `create_graphql_client`, `post_query`, and their language equivalents). ::: ### Enable SLOs on an HTTP Path or RPC Method **python** ```python import os import json # Reuse helpers defined earlier in this guide: # - get_causely_access_token # - create_graphql_client # - post_query CREATE_CONFIGS_MUTATION = """ mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } """ if __name__ == "__main__": cid, secret = os.getenv("CAUSELY_CLIENT_ID"), os.getenv("CAUSELY_CLIENT_SECRET") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") token = get_causely_access_token(cid, secret) client = create_graphql_client(token) # Replace with the entityId of the HTTP Path or RPC Method you want to enable SLOs on entity_id = "7c4bba4c-1942-5fc4-87e2-d1f2c483d2c2" variables = { "entityConfigs": [{ "type": "EntityTier", "entityId": entity_id, "data": "sloEnabled", }] } result = post_query(client, CREATE_CONFIGS_MUTATION, variables) print(json.dumps(result, indent=2)) ``` **javascript** ```javascript // Reuses helpers defined earlier in this guide: // - getCauselyAccessToken // - createGraphQLClient // - postQuery (for queries/mutations) const { gql } = require('@apollo/client'); const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; const CREATE_CONFIGS_MUTATION = ` mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } `; (async () => { if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET) { console.error('Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET'); process.exit(1); } const token = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const client = createGraphQLClient(token); // Replace with the entityId of the HTTP Path or RPC Method you want to enable SLOs on const entityId = '7c4bba4c-1942-5fc4-87e2-d1f2c483d2c2'; const variables = { entityConfigs: [ { type: 'EntityTier', entityId, data: 'sloEnabled', }, ], }; const result = await client.mutate({ mutation: gql(CREATE_CONFIGS_MUTATION), variables, }); console.log(JSON.stringify(result.data, null, 2)); })(); ``` **bash** ```bash #!/usr/bin/env bash set -euo pipefail # Prerequisites: # - CAUSELY_CLIENT_ID / CAUSELY_CLIENT_SECRET exported # - CAUSELY_ACCESS_TOKEN exported (see Authentication section) # - post_query / post_query_curl functions defined (see Bash GraphQL helpers section) # - jq installed # Replace with the entityId of the HTTP Path or RPC Method you want to enable SLOs on ENTITY_ID="7c4bba4c-1942-5fc4-87e2-d1f2c483d2c2" cat > create_entity_configs.graphql << 'EOF' mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } EOF cat > create_entity_configs_variables.json << EOF { "entityConfigs": [ { "type": "EntityTier", "entityId": "${ENTITY_ID}", "data": "sloEnabled" } ] } EOF QUERY=$(tr '\n' ' ' < create_entity_configs.graphql) VARIABLES=$(cat create_entity_configs_variables.json) post_query_curl "$QUERY" "$VARIABLES" rm -f create_entity_configs.graphql create_entity_configs_variables.json ``` **go** ```go package main import ( "encoding/json" "fmt" "os" ) // Reuse helpers defined earlier: // - getToken(id, secret, url) // - createGraphQLClient(accessToken string) *graphql.Client // - postQuery(client *graphql.Client, queryString string, variables map[string]interface{}) (interface{}, error) const createConfigsMutation = ` mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } ` func main() { id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET") if id == "" || secret == "" { fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") os.Exit(1) } token, err := getToken(id, secret, "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token") if err != nil { fmt.Fprintln(os.Stderr, "Error getting token:", err) os.Exit(1) } client := createGraphQLClient(token) // Replace with the entityId of the HTTP Path or RPC Method you want to enable SLOs on entityID := "7c4bba4c-1942-5fc4-87e2-d1f2c483d2c2" variables := map[string]interface{}{ "entityConfigs": []map[string]interface{}{ { "type": "EntityTier", "entityId": entityID, "data": "sloEnabled", }, }, } result, err := postQuery(client, createConfigsMutation, variables) if err != nil { fmt.Fprintln(os.Stderr, "Error enabling SLO:", err) os.Exit(1) } out, _ := json.MarshalIndent(result, "", " ") fmt.Println(string(out)) } ``` **graphql** ```graphql mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) { createEntityConfigs(entityConfigs: $entityConfigs) { entityId type data } } ``` **Variables (example):** ```json { "entityConfigs": [ { "type": "EntityTier", "entityId": "7c4bba4c-1942-5fc4-87e2-d1f2c483d2c2", "data": "sloEnabled" } ] } ``` ### Check whether an HTTP Path or RPC Method has SLOs enabled **python** ```python import os import json # Reuse helpers defined earlier: # - get_causely_access_token # - create_graphql_client # - post_query GET_CONFIGS_QUERY = """ query GetEntityConfigs($entityId: String!) { entityConfigs(entityId: $entityId) { type data entityId } } """ if __name__ == "__main__": cid, secret = os.getenv("CAUSELY_CLIENT_ID"), os.getenv("CAUSELY_CLIENT_SECRET") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") token = get_causely_access_token(cid, secret) client = create_graphql_client(token) entity_id = "2f3ce84a-18b8-5d4c-820d-5b747cbb7f13" result = post_query(client, GET_CONFIGS_QUERY, {"entityId": entity_id}) print(json.dumps(result, indent=2)) ``` **javascript** ```javascript const { gql } = require('@apollo/client'); const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; const GET_CONFIGS_QUERY = ` query GetEntityConfigs($entityId: String!) { entityConfigs(entityId: $entityId) { type data entityId } } `; (async () => { const token = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const client = createGraphQLClient(token); const entityId = '2f3ce84a-18b8-5d4c-820d-5b747cbb7f13'; const result = await client.query({ query: gql(GET_CONFIGS_QUERY), variables: { entityId }, fetchPolicy: 'no-cache', }); console.log(JSON.stringify(result.data, null, 2)); })(); ``` **bash** ```bash #!/usr/bin/env bash set -euo pipefail ENTITY_ID="2f3ce84a-18b8-5d4c-820d-5b747cbb7f13" cat > get_entity_configs.graphql << 'EOF' query GetEntityConfigs($entityId: String!) { entityConfigs(entityId: $entityId) { type data entityId } } EOF cat > get_entity_configs_variables.json << EOF { "entityId": "${ENTITY_ID}" } EOF QUERY=$(tr '\n' ' ' < get_entity_configs.graphql) VARIABLES=$(cat get_entity_configs_variables.json) post_query_curl "$QUERY" "$VARIABLES" rm -f get_entity_configs.graphql get_entity_configs_variables.json ``` **go** ```go package main import ( "encoding/json" "fmt" "os" ) // Reuse helpers defined earlier: // - getToken(id, secret, url) // - createGraphQLClient(accessToken string) *graphql.Client // - postQuery(client *graphql.Client, queryString string, variables map[string]interface{}) (interface{}, error) const getConfigsQuery = ` query GetEntityConfigs($entityId: String!) { entityConfigs(entityId: $entityId) { type data entityId } } ` func main() { id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET") if id == "" || secret == "" { fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") os.Exit(1) } token, err := getToken(id, secret, "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token") if err != nil { fmt.Fprintln(os.Stderr, "Error getting token:", err) os.Exit(1) } client := createGraphQLClient(token) // Replace with the entityId of the HTTP Path or RPC Method you want to inspect entityID := "2f3ce84a-18b8-5d4c-820d-5b747cbb7f13" variables := map[string]interface{}{ "entityId": entityID, } result, err := postQuery(client, getConfigsQuery, variables) if err != nil { fmt.Fprintln(os.Stderr, "Error querying configs:", err) os.Exit(1) } out, _ := json.MarshalIndent(result, "", " ") fmt.Println(string(out)) // Look for: type == "EntityTier" and data == "sloEnabled" } ``` **graphql** ```query GetEntityConfigs($entityId: String!) { entityConfigs(entityId: $entityId) { type data entityId } } ``` **Variables (example):** ```json { "entityId": "2f3ce84a-18b8-5d4c-820d-5b747cbb7f13" } ``` ### Remove SLOs from an HTTP Path or RPC Method **python** ```python import os import json # Reuse helpers defined earlier: # - get_causely_access_token # - create_graphql_client # - post_query DELETE_CONFIG_MUTATION = """ mutation DeleteEntityConfig($entityId: String!, $configType: String!) { deleteEntityConfig(entityId: $entityId, configType: $configType) } """ if __name__ == "__main__": cid, secret = os.getenv("CAUSELY_CLIENT_ID"), os.getenv("CAUSELY_CLIENT_SECRET") if not cid or not secret: raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") token = get_causely_access_token(cid, secret) client = create_graphql_client(token) entity_id = "2f3ce84a-18b8-5d4c-820d-5b747cbb7f13" result = post_query(client, DELETE_CONFIG_MUTATION, { "entityId": entity_id, "configType": "EntityTier" }) print(json.dumps(result, indent=2)) ``` **javascript** ```javascript const { gql } = require('@apollo/client'); const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env; const DELETE_CONFIG_MUTATION = ` mutation DeleteEntityConfig($entityId: String!, $configType: String!) { deleteEntityConfig(entityId: $entityId, configType: $configType) } `; (async () => { const token = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET); const client = createGraphQLClient(token); const entityId = '2f3ce84a-18b8-5d4c-820d-5b747cbb7f13'; const result = await client.mutate({ mutation: gql(DELETE_CONFIG_MUTATION), variables: { entityId, configType: 'EntityTier' }, }); console.log(JSON.stringify(result.data, null, 2)); })(); ``` **bash** ```bash #!/usr/bin/env bash set -euo pipefail ENTITY_ID="2f3ce84a-18b8-5d4c-820d-5b747cbb7f13" cat > delete_entity_config.graphql << 'EOF' mutation DeleteEntityConfig($entityId: String!, $configType: String!) { deleteEntityConfig(entityId: $entityId, configType: $configType) } EOF cat > delete_entity_config_variables.json << EOF { "entityId": "${ENTITY_ID}", "configType": "EntityTier" } EOF QUERY=$(tr '\n' ' ' < delete_entity_config.graphql) VARIABLES=$(cat delete_entity_config_variables.json) post_query_curl "$QUERY" "$VARIABLES" rm -f delete_entity_config.graphql delete_entity_config_variables.json ``` **go** ```go package main import ( "encoding/json" "fmt" "os" ) // Reuse helpers defined earlier: // - getToken(id, secret, url) // - createGraphQLClient(accessToken string) *graphql.Client // - postQuery(client *graphql.Client, queryString string, variables map[string]interface{}) (interface{}, error) const deleteConfigMutation = ` mutation DeleteEntityConfig($entityId: String!, $configType: String!) { deleteEntityConfig(entityId: $entityId, configType: $configType) } ` func main() { id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET") if id == "" || secret == "" { fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET") os.Exit(1) } token, err := getToken(id, secret, "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token") if err != nil { fmt.Fprintln(os.Stderr, "Error getting token:", err) os.Exit(1) } client := createGraphQLClient(token) // Replace with the entityId of the HTTP Path or RPC Method you want to remove SLOs from entityID := "2f3ce84a-18b8-5d4c-820d-5b747cbb7f13" variables := map[string]interface{}{ "entityId": entityID, "configType": "EntityTier", } result, err := postQuery(client, deleteConfigMutation, variables) if err != nil { fmt.Fprintln(os.Stderr, "Error deleting config:", err) os.Exit(1) } out, _ := json.MarshalIndent(result, "", " ") fmt.Println(string(out)) } ``` **graphql** ```graphql mutation DeleteEntityConfig($entityId: String!, $configType: String!) { deleteEntityConfig(entityId: $entityId, configType: $configType) } ``` **Variables (example):** ```json { "entityId": "2f3ce84a-18b8-5d4c-820d-5b747cbb7f13", "configType": "EntityTier" } ```