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

# Deployment & DORA Metrics

> API endpoints for deployment frequency, lead time for changes, change failure rate and time to restore

## Deployment & DORA Metrics

Deployment metrics cover how often you ship to production, how long changes take to get there, and how often they fail. How Bilanc detects a deployment and how the failure proxies work is explained in [DORA Metrics](/dora-metrics).

### Available Metrics

<ParamField path="deployment-frequency" type="string">
  Number of distinct production deployments. Table: `deployments`. Response column: `deployment_frequency`.
</ParamField>

<ParamField path="lead-time-for-changes-p50" type="string">
  Median seconds from first commit (or PR open, when no commit is known) to running in production. No aggregation parameter. Table: `pull_requests`. Response column: `lead_time_for_changes_p50`. This is what the dashboard shows.
</ParamField>

<ParamField path="lead-time-for-changes" type="string">
  Seconds from first commit (or PR open, when no commit is known) to running in production. Requires an aggregation. Table: `pull_requests`. Response column: `{agg}_lead_time_for_changes`.
</ParamField>

<ParamField path="change-failure-rate" type="string">
  Failed changes ÷ deployments, as a 0–1 fraction; remediation deployments are excluded from both sides. Table: `deployments`. Response column: `change_failure_rate`.
</ParamField>

<ParamField path="time-to-restore-p50" type="string">
  Median seconds from the bad change going live (or the incident opening, or the failed run) to production restored, over restored failed changes. No aggregation parameter. Table: `deployments`. Response column: `time_to_restore_p50`.
</ParamField>

<ParamField path="time-to-restore" type="string">
  Seconds from the bad change going live to production restored, over restored failed changes. Requires an aggregation. Table: `deployments`. Response column: `{agg}_time_to_restore`.
</ParamField>

<ParamField path="merge-to-deploy-p50" type="string">
  Median seconds from PR merge to running in production. No aggregation parameter. Table: `pull_requests`. Response column: `merge_to_deploy_p50`.
</ParamField>

<ParamField path="merge-to-deploy" type="string">
  Seconds from PR merge to running in production. Requires an aggregation. Table: `pull_requests`. Response column: `{agg}_merge_to_deploy`.
</ParamField>

<ParamField path="open-to-deploy" type="string">
  Seconds from PR open to running in production. Requires an aggregation. Table: `pull_requests`. Response column: `{agg}_open_to_deploy`.
</ParamField>

<ParamField path="queue-time" type="string">
  Seconds from entering a GitHub merge queue to merged. Requires an aggregation. Table: `pull_requests`. Response column: `{agg}_queue_time`.
</ParamField>

<ParamField path="deployment-success-rate" type="string">
  Successful ÷ all production deploy runs, as a 0–1 fraction. Table: `deployments`. Response column: `deployment_success_rate`.
</ParamField>

<ParamField path="prs-per-deployment" type="string">
  Pull requests carried per deployment. Requires an aggregation. Table: `deployments`. Response column: `{agg}_prs_per_deployment`.
</ParamField>

## Lead Time for Changes

Average lead time per repository, by week. Lead time lives on the `pull_requests` table, so it is bucketed by a PR date field.

<CodeGroup>
  ```bash Request theme={null}
  curl -X POST 'https://api.bilanc.co/metrics/lead-time-for-changes' \
    -H 'Authorization: YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "filters": {
        "repositories": [{"repository_name": "frontend-repo"}],
        "start_date": "2026-07-01",
        "end_date": "2026-08-15"
      },
      "aggregation": "avg",
      "group_by": ["repository_name"],
      "date_level": "week",
      "date_field": "pr_merged_at",
      "time_series_data": true
    }'
  ```

  ```json Response theme={null}
  {
    "series": [
      {
        "name": "frontend-repo",
        "data": [247320, 231840, 268560, 212400, 239760, 224280]
      },
      {
        "name": "backend-repo",
        "data": [98640, 104400, 91800, 110160, 95040, 101520]
      },
      {
        "name": "mobile-repo",
        "data": [612000, 589680, 640800, 601200, 576000, 622080]
      }
    ],
    "categories": ["Jul 6, 2026", "Jul 13, 2026", "Jul 20, 2026", "Jul 27, 2026", "Aug 3, 2026", "Aug 10, 2026"],
    "meta": {
      "filters": {
        "repositories": [{"repository_name": "frontend-repo"}],
        "start_date": "2026-07-01",
        "end_date": "2026-08-15"
      },
      "date_range": {
        "start_date": "2026-07-01",
        "end_date": "2026-08-15"
      }
    }
  }
  ```
</CodeGroup>

Values are seconds: `247320` is about 2.9 days.

## Change Failure Rate

Change failure rate per team, over a quarter. Deployment-level metrics live on the `deployments` table and are bucketed by `deployed_at`.

<CodeGroup>
  ```bash Request theme={null}
  curl -X POST 'https://api.bilanc.co/metrics/change-failure-rate' \
    -H 'Authorization: YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "filters": {
        "team": ["team123"],
        "start_date": "2026-04-01",
        "end_date": "2026-06-30"
      },
      "group_by": ["team_name"],
      "date_level": "quarter",
      "date_field": "deployed_at"
    }'
  ```

  ```json Response theme={null}
  {
    "results": [
      {
        "metric_name": "change-failure-rate",
        "value": 0.021,
        "group_by": {
          "team_name": "Platform Team"
        }
      },
      {
        "metric_name": "change-failure-rate",
        "value": 0.034,
        "group_by": {
          "team_name": "Frontend Team"
        }
      },
      {
        "metric_name": "change-failure-rate",
        "value": 0.012,
        "group_by": {
          "team_name": "Backend Team"
        }
      },
      {
        "metric_name": "change-failure-rate",
        "value": 0.058,
        "group_by": {
          "team_name": "Mobile Team"
        }
      }
    ],
    "meta": {
      "filters": {
        "team": ["team123"],
        "start_date": "2026-04-01",
        "end_date": "2026-06-30"
      },
      "date_range": {
        "start_date": "2026-04-01",
        "end_date": "2026-06-30"
      }
    }
  }
  ```
</CodeGroup>

## Parameter Notes

<ResponseField name="date_field" type="string">
  Deployment-level metrics (`deployment-frequency`, `deployment-success-rate`, `prs-per-deployment`, `change-failure-rate`, `time-to-restore`) read from the `deployments` table. The date field is `deployed_at`: when the release was published, the deploy run completed, or the PR merged for `merge_to_default` repositories.

  Lead-time metrics (`lead-time-for-changes`, `merge-to-deploy`, `open-to-deploy`, `queue-time`) read from the `pull_requests` table. Available date fields:

  * `pr_merged_at`: When the PR merged (default)
  * `pr_created_at`: When the PR was opened
</ResponseField>

<ResponseField name="aggregation" type="string">
  Required for `lead-time-for-changes`, `merge-to-deploy`, `open-to-deploy`, `queue-time`, `time-to-restore` and `prs-per-deployment`. Accepted values: `SUM`, `MAX`, `MIN`, `AVG`.
  Count and rate metrics (`deployment-frequency`, `deployment-success-rate`, `change-failure-rate`) and the median metrics (`lead-time-for-changes-p50`, `merge-to-deploy-p50`, `time-to-restore-p50`) do not take an aggregation.
</ResponseField>

<ResponseField name="filters" type="object">
  Applicable filters:

  * `repositories`: Array of `{"repository_name": "..."}` objects
  * `team`: Filter by team IDs
  * `squad_ids`: Filter by squad IDs
  * `squad_levels`: Filter by squad hierarchy level
  * `manager_ids`: Filter by manager user IDs
  * `departments`: Filter by department names
  * `member`: Filter by deployer or author merged user IDs
  * `locations`: Filter by employee location
  * `levels`: Filter by employee level

  Lead-time metrics also accept the pull request filters (`pr_states`, `sources`, `pr_categories`, `pr_ids`).
</ResponseField>

<ResponseField name="group_by" type="array">
  In addition to the people dimensions, deployment-level metrics can be grouped by `repository`, `deployment_source` (`bitbucket_deployment`, `github_release`, `workflow_run`, `merge_to_default`), `status`, `workflow_name` and `failure_reason` (`failed_deployment`, `incident`, `revert_pr`, `hotfix_pr`). Grouping by `deployment_source` is the quickest way to see which repositories are on a proxy.

  Lead-time metrics (and `pull-requests-count`) can be grouped by `deployment_attribution_status` (`deployed`, `awaiting_deploy`, `before_first_signal`, `non_production_branch`, `ignored`), `deployment_source`, `branching_model`, `is_promotion_pr` and `is_production_merge`. Grouping `pull-requests-count` by `deployment_attribution_status` gives the coverage figure the dashboard shows.
</ResponseField>

<ResponseField name="row-level export" type="object">
  To list deployments rather than aggregate them, call `deployment-frequency` with the row columns in `group_by` and `metric_min_value: 1`, for example `["deployment_id", "deployed_at", "repository", "deployment_source", "workflow_name", "version", "status", "prs_included", "failure_reason", "failure_detected_at", "remediation_merged_at", "restored_at", "pull_requests"]`. `pull_requests` is a JSON array of the pull requests the deployment carried. See [Data export](/api-reference/endpoint/data-export) for the pattern.
</ResponseField>

## Common Use Cases

* **DORA scorecard**: Pull all four metrics per team or repository for a monthly review
* **Release train impact**: Compare `merge-to-deploy` against pipeline duration to see how much lead time is waiting rather than building
* **Batch size**: Track `prs-per-deployment` as you move towards smaller, more frequent deployments
* **Proxy audit**: Group `deployment-frequency` by `deployment_source` to find repositories still on the `merge_to_default` fallback
