Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ org_id = "your-staging-org-id"
```

**To get these values:**
1. **org_id**: Settings → Organization → Copy the org ID (or from URL: `app.axiom.co/{org_id}/...`)
2. **token**: Settings → Profile → Personal Access Tokens → Create token (use a Personal Access Token, not an API token, for full query access)
- **`org_id`** - The organization ID. Get it from Settings → Organization.
- **`token`** - Use an advanced API token with minimal privileges.

The deployment name (e.g., `prod`, `staging`) is passed to scripts: `scripts/axiom-query prod "..."`

Expand Down
3 changes: 2 additions & 1 deletion skills/building-dashboards/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ token = "xaat-your-api-token"
org_id = "your-org-id"
```

Get your org_id from Settings → Organization. For the token, use a **Personal Access Token** (Settings → Profile → Personal Access Tokens) for full query access.
- **`org_id`** - The organization ID. Get it from Settings → Organization.
- **`token`** - Use an advanced API token with minimal privileges.

**Tip:** Run `scripts/setup` from the `axiom-sre` skill for interactive configuration.

Expand Down
11 changes: 5 additions & 6 deletions skills/building-dashboards/scripts/axiom-api
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
# Reads credentials from ~/.axiom.toml (shared with axiom-sre)
#
# Examples:
# axiom-api prod GET /internal/dashboards
# axiom-api prod GET /internal/dashboards/abc123
# axiom-api prod POST /internal/dashboards '{"name":"Test",...}'
# axiom-api prod GET /v2/user
# axiom-api prod GET /dashboards
# axiom-api prod GET /dashboards/abc123
# axiom-api prod POST /dashboards '{"name":"Test",...}'
# axiom-api prod GET /user

set -euo pipefail

Expand Down Expand Up @@ -59,8 +59,7 @@ if [[ -z "$URL" || -z "$TOKEN" || -z "$ORG_ID" ]]; then
exit 1
fi

# Dashboard API uses app.* instead of api.*
API_URL="${URL/api./app.}/api"
API_URL="${URL%/}/v2"

CURL_ARGS=(
-s
Expand Down
19 changes: 10 additions & 9 deletions skills/building-dashboards/scripts/dashboard-copy
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,26 @@ if [[ -z "$DEPLOYMENT" || -z "$ID" ]]; then
fi

# Fetch original
ORIGINAL=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" GET "/internal/dashboards/$ID")
ORIGINAL=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" GET "/dashboards/uid/$ID")

# Get original name if new name not provided
if [[ -z "$NEW_NAME" ]]; then
ORIG_NAME=$(echo "$ORIGINAL" | jq -r '.name')
ORIG_NAME=$(echo "$ORIGINAL" | jq -r '.dashboard.name')
NEW_NAME="${ORIG_NAME} (copy)"
fi

# Strip server fields and set new name
# Strip server fields and set new name on the dashboard subobject
BODY=$(echo "$ORIGINAL" | jq --arg name "$NEW_NAME" '
del(.id, .version, .createdAt, .updatedAt, .createdBy, .updatedBy) |
.dashboard |
del(.id, .uid, .version, .createdAt, .updatedAt, .createdBy, .updatedBy) |
.name = $name
')
' | jq '{dashboard: .}')

RESPONSE=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" POST "/internal/dashboards" "$BODY")
RESPONSE=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" POST "/dashboards" "$BODY")

# Print new ID and name
ID=$(echo "$RESPONSE" | jq -r '.id // empty')
NAME=$(echo "$RESPONSE" | jq -r '.name // empty')
# Print new UID and name
ID=$(echo "$RESPONSE" | jq -r '.dashboard.uid // empty')
NAME=$(echo "$RESPONSE" | jq -r '.dashboard.dashboard.name // empty')

if [[ -n "$ID" ]]; then
echo -e "${ID}\t${NAME}"
Expand Down
10 changes: 6 additions & 4 deletions skills/building-dashboards/scripts/dashboard-create
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ fi
# Read, strip server-managed fields, and normalize layout for react-grid-layout
BODY=$(jq -L "$SCRIPT_DIR" '
include "dashboard-normalize";
del(.id, .version, .createdAt, .updatedAt, .createdBy, .updatedBy) |
del(.id, .uid, .version, .createdAt, .updatedAt, .createdBy, .updatedBy) |
normalize_dashboard_layout
' "$JSON_FILE")

RESPONSE=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" POST "/internal/dashboards" "$BODY")
BODY=$(echo "$BODY" | jq '{dashboard: .}')

# Extract and print the new dashboard ID
ID=$(echo "$RESPONSE" | jq -r '.id // empty')
RESPONSE=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" POST "/dashboards" "$BODY")

# Extract and print the new dashboard UID
ID=$(echo "$RESPONSE" | jq -r '.dashboard.uid // empty')
if [[ -n "$ID" ]]; then
echo "$ID"
else
Expand Down
2 changes: 1 addition & 1 deletion skills/building-dashboards/scripts/dashboard-delete
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 0
fi

"$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" DELETE "/internal/dashboards/$ID"
"$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" DELETE "/dashboards/uid/$ID"
echo "Deleted: $ID"
2 changes: 1 addition & 1 deletion skills/building-dashboards/scripts/dashboard-get
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ if [[ -z "$DEPLOYMENT" || -z "$ID" ]]; then
exit 1
fi

"$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" GET "/internal/dashboards/$ID" | jq .
"$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" GET "/dashboards/uid/$ID" | jq '.dashboard'
4 changes: 2 additions & 2 deletions skills/building-dashboards/scripts/dashboard-list
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ if [[ -z "$DEPLOYMENT" ]]; then
exit 1
fi

RESPONSE=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" GET "/internal/dashboards?limit=1000")
RESPONSE=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" GET "/dashboards?limit=1000")

if [[ "$FORMAT" == "--json" ]]; then
echo "$RESPONSE" | jq .
else
echo "$RESPONSE" | jq -r '.[] | [.id, .name] | @tsv'
echo "$RESPONSE" | jq -r '.[] | [.uid, .dashboard.name] | @tsv'
fi
8 changes: 7 additions & 1 deletion skills/building-dashboards/scripts/dashboard-update
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ if [[ -z "$VERSION" ]]; then
exit 1
fi

RESPONSE=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" PUT "/internal/dashboards/$ID" "$BODY")
# Wrap body in v2 envelope: {dashboard: {...}, version: N}
# Version must be a numeric int64. jq loses precision on large integers,
# so we inject it via string substitution.
DASHBOARD=$(echo "$BODY" | jq 'del(.version)')
BODY="{\"dashboard\":${DASHBOARD},\"version\":${VERSION}}"

RESPONSE=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" PUT "/dashboards/uid/$ID" "$BODY")

echo "$RESPONSE" | jq .
16 changes: 8 additions & 8 deletions skills/building-dashboards/tests/test-script-output.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ METHOD="${2:-}"
PATH_="${3:-}"

case "$METHOD:$PATH_" in
"POST:/internal/dashboards")
echo '{"id":"created-id"}'
"POST:/dashboards")
echo '{"status":"created","dashboard":{"uid":"created-uid","id":"created-id","version":1,"dashboard":{"name":"Test Dashboard"},"createdAt":"2026-02-01T10:00:00Z","updatedAt":"2026-02-01T10:00:00Z","createdBy":"alice@example.com","updatedBy":"alice@example.com"}}'
;;
"PUT:/internal/dashboards/dashboard-root-id")
echo '{"id":"dashboard-root-id","updated":true}'
"PUT:/dashboards/uid/dashboard-root-id")
echo '{"status":"updated","dashboard":{"uid":"dashboard-root-id","id":"dashboard-root-id","version":2,"dashboard":{"name":"Test Dashboard","updated":true},"createdAt":"2026-02-01T10:00:00Z","updatedAt":"2026-02-02T11:00:00Z","createdBy":"alice@example.com","updatedBy":"bob@example.com"}}'
;;
*)
echo "Unexpected call: $METHOD $PATH_" >&2
Expand All @@ -83,14 +83,14 @@ echo "Script Stdout Contract"
echo "======================"

create_out=$("$TMPDIR/dashboard-create" prod "$TMPDIR/input.json")
if [[ "$create_out" == "created-id" ]]; then
ok "dashboard-create outputs only dashboard ID"
if [[ "$create_out" == "created-uid" ]]; then
ok "dashboard-create outputs only dashboard UID"
else
fail "dashboard-create outputs only dashboard ID" "got: $create_out"
fail "dashboard-create outputs only dashboard UID" "got: $create_out"
fi

update_out=$("$TMPDIR/dashboard-update" prod dashboard-root-id "$TMPDIR/input.json")
if echo "$update_out" | jq -e '.id == "dashboard-root-id" and .updated == true' > /dev/null 2>&1; then
if echo "$update_out" | jq -e '.dashboard.uid == "dashboard-root-id" and .dashboard.dashboard.updated == true' > /dev/null 2>&1; then
ok "dashboard-update outputs valid JSON only"
else
fail "dashboard-update outputs valid JSON only" "got: $update_out"
Expand Down
3 changes: 2 additions & 1 deletion skills/controlling-costs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ token = "xaat-your-api-token"
org_id = "your-org-id"
```

Get your org_id from Settings → Organization. For the token, use a **Personal Access Token** (Settings → Profile → Personal Access Tokens) for full query access.
- **`org_id`** - The organization ID. Get it from Settings → Organization.
- **`token`** - Use an advanced API token with minimal privileges.

**Tip:** Run `scripts/setup` from the `axiom-sre` skill for interactive configuration.

Expand Down
2 changes: 1 addition & 1 deletion skills/query-metrics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ token = "xaat-your-api-token"
org_id = "your-org-id"
```

Get your org_id from Settings → Organization. For the token, use a **Personal Access Token** (Settings → Profile → Personal Access Tokens) for full query access.
Get your org_id from Settings → Organization. For the token, create a scoped **API token** (Settings → API Tokens) with the permissions your workflow needs. Avoid Personal Access Tokens for automated tooling.

**Tip:** Run `scripts/setup` from the `axiom-sre` skill for interactive configuration.

Expand Down
2 changes: 1 addition & 1 deletion skills/query-metrics/scripts/resolve-url
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extract_value() {
FALLBACK_URL=$(extract_value "url")

REGION=$("$SCRIPT_DIR/axiom-api" "$DEPLOYMENT" GET /v1/datasets \
| jq -r --arg name "$DATASET" '.[] | select(.name == $name) | .region // empty')
| jq -r --arg name "$DATASET" '.[] | select(.name == $name) | .edgeDeployment // .region // empty')

if [[ -z "$REGION" || "$REGION" == "null" ]]; then
echo "$FALLBACK_URL"
Expand Down
2 changes: 1 addition & 1 deletion skills/query-metrics/scripts/setup
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ org_id = "your-org-id"
EOF
echo ""
echo "Get your org_id from Settings → Organization."
echo "For the token, use a Personal Access Token (Settings → Profile → Personal Access Tokens)."
echo "For the token, create a scoped API token (Settings → API Tokens) with the permissions your workflow needs."
fi

echo ""
Expand Down
2 changes: 1 addition & 1 deletion skills/spl-to-apl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ token = "xaat-your-api-token"
org_id = "your-org-id"
```

Get your org_id from Settings → Organization. For the token, use a **Personal Access Token** (Settings → Profile → Personal Access Tokens) for full query access.
Get your org_id from Settings → Organization. For the token, create a scoped **API token** (Settings → API Tokens) with the permissions your workflow needs. Avoid Personal Access Tokens for automated tooling.

## Related Skills

Expand Down
2 changes: 1 addition & 1 deletion skills/sre/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ token = "xaat-your-api-token"
org_id = "your-org-id"
```

Get your org_id from Settings → Organization. For the token, use a **Personal Access Token** (Settings → Profile → Personal Access Tokens) for full query access.
Get your org_id from Settings → Organization. For the token, create a scoped **API token** (Settings → API Tokens) with the permissions your workflow needs. Avoid Personal Access Tokens for automated tooling.

## Usage

Expand Down
9 changes: 4 additions & 5 deletions skills/sre/reference/api-capabilities.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# Axiom API Capabilities

Summary of all operations available via Axiom API with a personal access token (PAT).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes in skills/sre need to happen in gilfoyle first, and then they will be synced over automatically.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here it's: axiomhq/gilfoyle#15

Summary of all operations available via Axiom API.

**Base URL:** `https://api.axiom.co` (for all endpoints except ingestion)
**Ingest URL:** Use edge deployment domain (e.g., `https://us-east-1.aws.edge.axiom.co`)
**Base URL:** `https://api.axiom.co` (for management endpoints)
**Query & Ingest URL:** Auto-resolved per dataset via `scripts/resolve-url`

**Authentication:**
- PAT: `Authorization: Bearer $PAT` + `x-axiom-org-id: $ORG_ID`
- API Token: `Authorization: Bearer $API_TOKEN`
- `Authorization: Bearer $API_TOKEN` — use an advanced API token with minimal privileges

---

Expand Down
9 changes: 4 additions & 5 deletions skills/sre/reference/axiom.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# Axiom API Capabilities

Summary of all operations available via Axiom API with a personal access token (PAT).
Summary of all operations available via Axiom API.

**Base URL:** `https://api.axiom.co` (for all endpoints except ingestion)
**Ingest URL:** Use edge deployment domain (e.g., `https://us-east-1.aws.edge.axiom.co`)
**Base URL:** `https://api.axiom.co` (for management endpoints)
**Query & Ingest URL:** Auto-resolved per dataset via `scripts/resolve-url`

**Authentication:**
- PAT: `Authorization: Bearer $PAT` + `x-axiom-org-id: $ORG_ID`
- API Token: `Authorization: Bearer $API_TOKEN`
- `Authorization: Bearer $API_TOKEN` — use an advanced API token with minimal privileges

---

Expand Down
28 changes: 26 additions & 2 deletions skills/sre/scripts/axiom-api
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,32 @@ fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
eval "$("$SCRIPT_DIR/config" axiom "$DEPLOYMENT")"

# Auto-resolve edge URL for query and ingest endpoints
REQUEST_URL="$AXIOM_URL"
REQUEST_ENDPOINT="$ENDPOINT"
case "$ENDPOINT" in
/v1/datasets/_apl*|/v1/ingest/*)
DATASET=""
if [[ "$ENDPOINT" == /v1/ingest/* ]]; then
DATASET="${ENDPOINT#/v1/ingest/}"
DATASET="${DATASET%%[?/]*}"
elif [[ -n "$BODY" ]]; then
DATASET=$(echo "$BODY" | jq -r '.apl // empty' 2>/dev/null | grep -oE "^\['[^']+'\]|^\[\"[^\"]+\"\]|^\[[a-zA-Z0-9_-]+\]" | head -1 | tr -d "[]'\"" || true)
fi
if [[ -n "$DATASET" ]]; then
RESOLVED=$("$SCRIPT_DIR/resolve-url" "$DEPLOYMENT" "$DATASET" 2>/dev/null || true)
if [[ -n "$RESOLVED" && "$RESOLVED" != "$AXIOM_URL" ]]; then
REQUEST_URL="$RESOLVED"
if [[ "$ENDPOINT" == /v1/datasets/_apl* ]]; then
REQUEST_ENDPOINT="/v1/query/_apl${ENDPOINT#/v1/datasets/_apl}"
fi
fi
fi
;;
esac

if [[ -n "$BODY" ]]; then
"$SCRIPT_DIR/curl-auth" axiom "$DEPLOYMENT" -X "$METHOD" -d "$BODY" "${AXIOM_URL}${ENDPOINT}"
"$SCRIPT_DIR/curl-auth" axiom "$DEPLOYMENT" -X "$METHOD" -d "$BODY" "${REQUEST_URL}${REQUEST_ENDPOINT}"
else
"$SCRIPT_DIR/curl-auth" axiom "$DEPLOYMENT" -X "$METHOD" "${AXIOM_URL}${ENDPOINT}"
"$SCRIPT_DIR/curl-auth" axiom "$DEPLOYMENT" -X "$METHOD" "${REQUEST_URL}${REQUEST_ENDPOINT}"
fi
2 changes: 1 addition & 1 deletion skills/sre/scripts/axiom-link
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ fi
# Derive web UI URL from configured API URL
# Replace "api." with "app." in the domain
# Examples:
# https://api.axiom.co → https://app.axiom.co
# https://api.staging.axiom.co → https://app.staging.axiom.co
# https://api.dev.axiom.co → https://app.dev.axiom.co
# https://cloud.axiom.co → https://app.axiom.co
# https://api.axiom.co → https://app.axiom.co
if [[ "$URL" == *"cloud.axiom.co"* ]]; then
BASE_URL="https://app.axiom.co"
elif [[ "$URL" == https://api.* ]]; then
Expand Down
14 changes: 13 additions & 1 deletion skills/sre/scripts/axiom-query
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,21 @@ cleanup() {
}
trap cleanup EXIT

# Auto-resolve edge URL
QUERY_URL="$AXIOM_URL"
QUERY_PATH="/v1/datasets/_apl?format=tabular"
DATASET=$(echo "$APL" | grep -oE "^\['[^']+'\]|^\[\"[^\"]+\"\]|^\[[a-zA-Z0-9_-]+\]" | head -1 | tr -d "[]'\"" || true)
if [[ -n "$DATASET" ]]; then
RESOLVED=$("$SCRIPT_DIR/resolve-url" "$DEPLOYMENT" "$DATASET" 2>/dev/null || true)
if [[ -n "$RESOLVED" && "$RESOLVED" != "$AXIOM_URL" ]]; then
QUERY_URL="$RESOLVED"
QUERY_PATH="/v1/query/_apl?format=tabular"
fi
fi

# Execute query and pipe to formatter
HTTP_CODE=$(curl -sS -o "$RESP_BODY" -D "$RESP_HEADERS" -w "%{http_code}" \
-X POST "$AXIOM_URL/v1/datasets/_apl?format=tabular" \
-X POST "$QUERY_URL$QUERY_PATH" \
-H "Authorization: Bearer $AXIOM_TOKEN" \
-H "X-Axiom-Org-Id: $AXIOM_ORG_ID" \
-H "Content-Type: application/json" \
Expand Down
Loading
Loading