> ## Documentation Index
> Fetch the complete documentation index at: https://docs.periscope.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Ingest deployment

> Send a deployment event to Periscope from your CI/CD pipeline.

## Endpoint

```
POST https://app.periscope.sh/api/webhooks/deployments
```

## Headers

| Header          | Required | Value                 |
| --------------- | -------- | --------------------- |
| `Authorization` | Yes      | `Bearer YOUR_API_KEY` |
| `Content-Type`  | Yes      | `application/json`    |

## Request body

```json theme={"system"}
{
  "deploymentId": "gha-12345",
  "commitSha": "a1b2c3d4e5f60ab2c3d4e5f60ab2c3d4e5f60ab2",
  "environment": "production",
  "status": "success",
  "startedAt": "2024-01-15T10:30:00Z",
  "completedAt": "2024-01-15T10:35:00Z",
  "service": "api-gateway",
  "branch": "main",
  "triggeredBy": "alice@company.com",
  "pipelineName": "Production Deploy",
  "pipelineUrl": "https://github.com/org/repo/actions/runs/12345"
}
```

See the [payload schema](/api-reference/payload-schema) for the full field reference.

## Response

### Success — new deployment (201)

```json theme={"system"}
{
  "action": "created",
  "deploymentId": 42,
  "linkedPRs": 3
}
```

### Success — updated existing (200)

When a deployment with the same `deploymentId` already exists:

```json theme={"system"}
{
  "action": "updated",
  "deploymentId": 42,
  "linkedPRs": 3
}
```

### Validation error (400)

```json theme={"system"}
{
  "error": "Invalid payload: commitSha must be a valid hex string (5-40 characters)"
}
```

### Authentication error (401)

```json theme={"system"}
{
  "error": "Invalid or missing API key"
}
```

### Organization mismatch (403)

When `organizationSlug` in the payload does not match the key's organization:

```json theme={"system"}
{
  "error": "Organization slug does not match API key"
}
```

## Behavior

### Idempotency

The `deploymentId` field is the idempotency key. Sending the same `deploymentId` twice updates the existing record rather than creating a duplicate. This is safe for retries.

### PR linking

On successful production deployments, Periscope automatically links the deployment to merged PRs using the `commitSha` and calculates lead time for each linked PR.

### Free trial

If your organization is on the Free plan, the first deployment event starts a 14-day Business trial.

## Example

```bash theme={"system"}
curl -X POST https://app.periscope.sh/api/webhooks/deployments \
  -H "Authorization: Bearer psk_live_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "deploymentId": "deploy-001",
    "commitSha": "abc123def456abc123def456abc123def456abc1",
    "environment": "production",
    "status": "success",
    "startedAt": "2024-01-15T10:30:00Z",
    "completedAt": "2024-01-15T10:35:00Z",
    "service": "my-api"
  }'
```
