---
sidebar_position: 4
title: API Keys & Webhooks Reference
description: Reference for Myop self-hosting API keys, webhook payload format, signature verification, and delivery logging.
keywords: [myop api key, webhook payload, signature verification, hmac, self-hosting reference]
---
# API Keys & Webhooks Reference

## API Keys

API keys authenticate server-to-server requests to the Myop export API. They're used by CI/CD pipelines and the `myop` CLI.

### Creating a Key

1. Go to **Dashboard > Rollout > Settings (gear icon) > Self-Hosting**
2. Scroll to **API Keys** and click **Create API Key**
3. Give it a name (e.g., "GitHub Actions Sync" or "Production CI")
4. Copy the full key — **it's only shown once**

Keys have the format: `myop_sk_<64-char-hex>`

### Using a Key

```bash
# Via CLI
npx myop export --api-key myop_sk_abc123...

# Via environment variable (recommended for CI)
export MYOP_API_KEY=myop_sk_abc123...
npx myop export

# Direct API call
curl -H "Authorization: Bearer myop_sk_abc123..." \
  https://cloud.myop.dev/export
```

### Revoking a Key

Click **Revoke** next to any key in the Self-Hosting settings. Revoked keys stop working immediately. Active CI/CD pipelines using a revoked key will fail on their next run.

---

## Webhooks

### Delivery Methods

| Method | Setup | Best For |
|--------|-------|----------|
| **GitHub Actions** | Click "Add GitHub Actions" in dashboard | GitHub users — one-click, no secrets to manage |
| **Generic Webhook** | Enter any URL | Jenkins, GitLab CI, CircleCI, custom servers |

### Event Types

| Event | Trigger |
|-------|---------|
| `components.deployed` | A component variant was released to an environment |

### Webhook Payload (Generic)

```json
{
  "event": "components.deployed",
  "timestamp": "2026-03-24T13:37:00.000Z",
  "organizationId": "org-abc-123",
  "data": {
    "releases": [
      {
        "componentId": "2098cfba-5124-48ff-b87d-6cd71c14cf7a",
        "variantId": "57a5c9ef-8775-4a19-a243-4cadb87a3e6f",
        "environment": "production",
        "environmentId": "d6c518e0-f80b-4cbe-9efd-b51aa37f2324"
      }
    ]
  }
}
```

### Webhook Payload (GitHub Actions)

GitHub Actions webhooks are sent as `repository_dispatch` events:

```json
{
  "event_type": "myop-components-deployed",
  "client_payload": {
    "releases": [
      {
        "componentId": "2098cfba-5124-48ff-b87d-6cd71c14cf7a",
        "variantId": "57a5c9ef-8775-4a19-a243-4cadb87a3e6f",
        "environment": "production",
        "environmentId": "d6c518e0-f80b-4cbe-9efd-b51aa37f2324"
      }
    ]
  }
}
```

### Headers (Generic)

| Header | Description |
|--------|-------------|
| `Content-Type` | `application/json` |
| `X-Myop-Event` | Event type: `components.deployed` |
| `X-Myop-Signature` | HMAC-SHA256 signature of the body |

### Signature Verification

When you add a generic webhook, Myop generates a signing secret (`whsec_...`). Every payload is signed with HMAC-SHA256 using this secret. **Always verify signatures** to ensure requests are from Myop.

```javascript
const crypto = require('crypto');

function verifyWebhook(rawBody, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
```

:::warning
The signing secret is only shown once when the webhook is created. If you lose it, remove the webhook and add it again to get a new secret.
:::

### Using the Releases Payload

The `releases` array tells you exactly which components changed. Pass it directly to the CLI for an incremental sync:

```bash
npx myop export --releases '[{"componentId":"...","environment":"production","environmentId":"...","variantId":"..."}]'
```

Or for a full sync (ignoring the payload):

```bash
npx myop export
```

### Delivery Status

The Self-Hosting settings show real-time delivery status for each webhook:

- **Green dot** with status code (e.g., `204 2m ago`) — Last delivery succeeded
- **Red dot** with `Failed` — Last delivery failed (timeout, connection error, or non-2xx response)

### Delivery Policy

| Property | Value |
|----------|-------|
| Timeout | 10 seconds |
| Retries | None (fire-and-forget) |
| Fallback | Use scheduled sync (e.g., daily cron) |

:::tip
Always configure a scheduled fallback (e.g., GitHub Actions cron `0 0 * * *` or a daily full sync in your CI) to catch any missed webhook deliveries.
:::
