# Keys

> Part of the Cowliss docs. Markdown for every page: append `index.md` to its URL. Site map: /llms.txt

An org issues two kinds of key, and neither can do the other's job. Both live under **Settings → Credentials**, where any member can list them and an `org:admin` creates and revokes them, and both show their secret exactly once, on the create response.

## API keys

An API key authenticates `identify`, `track`, and `batch`. It is org-level: the source comes from the payload, never the key, so one key serves every app you point at Cowliss. Any member can list them; creating and revoking is `org:admin`.

```bash
cow settings apiKeys create --name "storefront"
cow settings apiKeys list
cow settings apiKeys revoke ak_... --revocation-reason "rotated"
```

An API key cannot reach the dashboard API at all, including the push loop. Sending one to `/v1/pushes` is a **401**, exactly as an unknown key would be.

## Pipeline keys

A pipeline key is the credential a pipeline uses to ship a repo without a human session. It reaches one subtree and a handful of exact paths, and nothing else: `/v1/pushes`, an app's status, the two execution reads, and an automation's `enable` and `disable`. Reading one key's version history is a dashboard question, so `/v1/versions` is not on the list, and neither is `/v1/executions/cancel`: a pipeline sees what its push started, and stopping runs that are carrying real people is a person's call. For the same reason a push with `--prune` is refused: it would delete automations.

```bash
cow settings pipelineKeys create --name "ci-deploy"
cow settings pipelineKeys list
cow settings pipelineKeys revoke ak_... --revocation-reason "pipeline retired"
```

On those, a pipeline key acts as an admin: it turns an automation on. Everywhere else it is a **401** with no hint that it is a valid credential of any kind: settings, API keys, users, events, segments, and ingestion all refuse it. Revoking one takes effect on its next request: unlike API keys, pipeline keys are never cached, because revoking is the whole incident response for a leaked pipeline credential.

So the pipeline key is exactly as powerful as shipping your repo and no more, and if it leaks nobody reads your customer data with it.

## Who can do what

With a signed-in session:

| Action | Role |
| --- | --- |
| Plan and push | any member |
| Turn an automation on or off | `org:admin` |
| Cancel live executions | `org:admin` |
| Create or revoke either kind of key | `org:admin` |

An automation carries one switch, so `cow enable <key>` and `cow disable <key>` take the key and nothing else.

## Using a pipeline key from CI

Set `COW_PIPELINE_KEY`. The CLI prefers it over `COW_TOKEN` and over a cached `cow login`, so a stale session on the build box can never become the identity a pipeline runs as. `cow whoami` says which credential is in play.

```yaml
env:
  COW_PIPELINE_KEY: ${{ secrets.COW_PIPELINE_KEY }}
steps:
  - run: cow whoami # {"credential":"pipelineKey",...}
  - run: cow plan
```

The rest of what a pipeline runs is in [Your repo](/guides/repo/). A member's own laptop needs none of this: `cow login`, and everything that follows acts on the organization you are signed in to.
