axonpush
Getting started

Browser authentication

How the integrate skill gets an API key without your copying one, the local callback listener, its two backends, and the three fallbacks when it cannot run.

The axonpush-integrate skill needs an API key and a tenant ID. Rather than asking you to find them in the dashboard and paste them into a terminal, it runs a small login helper that gets them out of a browser session you are probably already signed into.

The helper is skills/axonpush-integrate/helpers/login.sh in axonpush/skills. Every supported agent runs the same script.

The flow

  1. The helper picks a free port N on 127.0.0.1 and starts a listener there.
  2. It opens https://app.axonpush.xyz/wizard-auth?port=N in your browser.
  3. You sign in, or you already are, pick an organisation, then click Generate API Key and Send to Wizard.
  4. The page redirects to http://127.0.0.1:N/callback?api_key=…&tenant_id=….
  5. The listener reads both values, prints {"api_key": "…", "tenant_id": "…"} to stdout, and shuts down.
  6. The skill parses that and calls helpers/env.sh, which writes the credentials to .env.local if that file already exists, and to .env otherwise.

The callback path is /callback. A request to any other path gets a Waiting for authentication… holding page, and a /callback missing either field gets a 400. The listener only exits once it has both.

Everything is subject to a 120-second timeout. Exit codes are 0 for success, 1 for a timeout or missing fields, and 2 when no listener tool is available.

Listener backends

The helper needs one of two things on your PATH:

  • python3, preferred. A http.server.BaseHTTPRequestHandler bound to 127.0.0.1.
  • nc, fallback, invoked as nc -l -p $PORT -q 1.

If neither exists it exits 2 immediately without opening a browser. That is the most common failure on a minimal container image, and it is not a network problem, install one of the two, or use the manual fallback below.

To open the browser it tries xdg-open, then open, then start. When none of them work it prints the URL for you to open by hand, which is what makes this workable over SSH with local port forwarding.

When the browser flow will not work

Three ways round it, and the skill offers them in this order.

Credentials already in the environment

If AXONPUSH_API_KEY and AXONPUSH_TENANT_ID are already set, the skill skips login entirely. In CI, or on a machine you have already configured, this is the path you want.

MCP

If an axonpush MCP server exposing provision_app is connected to your agent, the skill uses it instead of the browser. It calls provision_app({ appName, channelNames, environment? }) and receives a one-time ingest key. The MCP token needs the mcp:setup scope.

The key this returns is publish-only, which is why the skill verifies the integration through the MCP server’s search_events rather than through the REST list endpoint, a publish-only key cannot read events back.

Paste a key

Choose Enter API key manually and paste one from the dashboard. The skill writes the same file and continues from step 6. AXONPUSH_TENANT_ID defaults to 1 if you do not supply one, which is only right on a single-tenant deployment, check it.

Self-host

Set AXONPUSH_BASE_URL to your own deployment before running the skill. The login helper also takes the app URL as its first positional argument, so bash login.sh https://app.axonpush.internal points the browser flow at a self-hosted dashboard.

What the key is used for

The skill talks to the REST API with two headers:

X-API-Key: <key>
x-tenant-id: <tenant>

It uses them to create an app and channels, publish a test event, and read that event back. Nothing else.

The key the dashboard generates for the wizard is named wizard-generated and carries a broad set of scopes: publish, events:read, traces:read, analytics:read, alerts:manage, apps:manage, channels:manage and webhooks:manage. That is a broad key for an application to hold in production, treat it as a development credential and mint a narrower, environment-pinned one for deploys. See Environments.

Security notes

  • The listener binds to 127.0.0.1 only, never to a network interface.
  • It serves exactly one path that matters and exits as soon as it has both credentials, but it is a real HTTP listener while it waits, and it waits up to 120 seconds. It is not a single-shot socket.
  • Credentials land in .env.local or .env. The skill checks .gitignore and adds the file if it is missing.
  • The key is organisation-scoped and revocable from the dashboard at any time.
  • The key travels in a URL query string on a loopback redirect, which means it can reach your browser’s history. Rotate it if that matters to you.