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

# Get catchment metrics

> Requested catchment metrics and, when selected, separate local-authority fee/occupancy values for the postcode. Supply exactly one of drive_minutes or radius_miles. The request reserves the number of unique metrics; successful non-null values consume one credit each.

## Geography

Catchments use cumulative, precomputed H3 resolution-8 bands around the postcode's origin cell. Postcodes in the same cell resolve to the same catchment. Radius is a grid approximation of a circle; drive time uses precomputed road-network bands. No saved-site filters or manually edited catchment boundaries are applied.

The authority lookup uses the postcode point. `local_authority.requested_area` identifies its district; `authority` identifies the social-care authority, often the parent county. A radius crossing several authorities still returns authority metrics for the postcode, not an average across the circle. Each authority value also identifies its actual `reporting_authority`.

## Values and availability

`values` and `metric_details` contain requested catchment keys. Authority keys, when requested, are returned separately in `local_authority.values` and `local_authority.metric_details`. Each metric is available or unavailable; missing data stays null. A valid request can contain both. Values follow the catalogue's rounding and null policy.

Open, non-specialist care homes form the older-person bed supply. Undersupply subtracts each bed category from the same modelled demand and retains negative values for surplus. The three undersupply figures overlap and must not be added together. They exclude planning; permitted and undecided pipeline beds are separate metrics.

Private residential and nursing quoted fees remain separate. Bed-weighted means use each contributing home's total beds, not an observed number of residents paying that fee. Residential fee publication requires at least five homes and 150 covered beds; nursing requires three homes and 100 beds. Below-threshold fees are null, with sample counts and bed coverage in the details. Five years of historical private fees is not available.

## Projection and periods

Without `projection_year`, demand uses the source-population age bands. With it, the postcode centroid is converted to a resolution-8 H3 cell. The projection service selects the LAD with the largest recorded overlap for that cell, and uses its factors for supported population counts and derived demand/undersupply. The same factors apply throughout the catchment. Current published supply, fees, planning and authority figures are unchanged. Missing required factors can make projected metrics unavailable.

`population_projection_year` on demand and undersupply details is null when unprojected. Unprojected undersupply combines source-period demand with current published supply. `data_version` identifies the demographic catchment build; other published datasets are read at request time and are not historical snapshots of that build.

## Credits

The full number of unique requested metrics must be available for reservation. Only usable numeric values in the successful response consume credits, including zero. Unavailable values release their reservation. See the [credit and request rules](https://docs.catchment.app/index.md#credits).


## OpenAPI

````yaml /api-reference/openapi.json get /v1/catchment-metrics
openapi: 3.1.0
info:
  title: Catchment API
  version: 1.1.0
  description: >-
    Postcode catchment, H3 cell and local-authority metrics, with a discoverable
    metric catalogue, area mappings and organisation-level trial credits. Access
    must be explicitly enabled for the organisation. This reference describes
    the current implementation; availability depends on the deployed version.
servers:
  - url: https://api.catchment.app
security:
  - bearerAuth: []
tags:
  - name: Catchments
    description: Metric values for a catchment around a postcode.
  - name: Cells
    description: Metric values for a single H3 cell.
  - name: Area mappings
    description: Overlaps between statistical areas and H3 cells.
  - name: Metrics
    description: The metrics available to request.
  - name: Local authorities
    description: Fee and occupancy values for the reporting authority.
paths:
  /v1/catchment-metrics:
    get:
      tags:
        - Catchments
      summary: Get catchment metrics
      description: >-
        Requested catchment metrics and, when selected, separate local-authority
        fee/occupancy values for the postcode. Supply exactly one of
        drive_minutes or radius_miles. The request reserves the number of unique
        metrics; successful non-null values consume one credit each.
      operationId: getCatchmentMetrics
      parameters:
        - name: postcode
          in: query
          required: true
          description: >-
            UK postcode. Case and spacing are ignored. Resolved to its centroid
            in the ONS Postcode Directory.
          schema:
            type: string
            example: ME14 1XQ
        - name: drive_minutes
          in: query
          required: false
          description: >-
            Drive-time catchment in minutes. Mutually exclusive with
            `radius_miles`.
          schema:
            type: integer
            minimum: 1
            maximum: 25
            example: 10
        - name: radius_miles
          in: query
          required: false
          description: >-
            Radius catchment in miles, measured in a straight line. Mutually
            exclusive with `drive_minutes`.
          schema:
            type: integer
            minimum: 1
            maximum: 10
        - name: metrics
          in: query
          required: true
          description: >-
            Comma-separated keys supporting catchment or local_authority. At
            most 50 distinct keys; duplicates and empty entries are removed. The
            catalogue is filtered by organisation access.
          schema:
            type: string
            example: >-
              avg_price,carehome_demand,existing_beds_all,bed_weighted_avg_fee_residential_week,bed_weighted_avg_fee_nursing_week,la_occupancy_pct
        - name: projection_year
          in: query
          required: false
          description: Year to project population counts to. Omit for observed values.
          schema:
            type: integer
            minimum: 2026
            maximum: 2035
            example: 2032
      responses:
        '200':
          description: Metric values for the catchment.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateLimitRemaining'
            X-Credits-Used:
              $ref: '#/components/headers/CreditsUsed'
            X-Credits-Remaining:
              $ref: '#/components/headers/CreditsRemaining'
            Cache-Control:
              $ref: '#/components/headers/CacheControl'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CatchmentMetricsResponse'
              example:
                request_id: ee49f8a0-d6b2-46ec-91b5-b066641996a0
                catchment:
                  cell_count: 133
                  miles: 3
                  type: radius
                data_version: demographics_build:8eac09a5-bcf1-48cb-a2c2-d3a33a52ee7c
                location:
                  latitude: 51.2786
                  longitude: 0.522342
                  postcode: ME14 1XQ
                  postcode_terminated_on: null
                projection_year: null
                values:
                  avg_price: 368531
                  population_85_plus_pct: 2.5
                  carehome_demand: 790
                  existing_beds_all: 1208
                  existing_beds_ensuite: 913
                  existing_beds_wetroom: 405
                  undersupply_existing_all: -418
                  undersupply_existing_ensuite: -123
                  undersupply_existing_wetroom: 385
                  bed_weighted_avg_fee_residential_week: 1609
                  bed_weighted_avg_fee_nursing_week: 1794
                  planned_permitted_beds: 0
                  planned_undecided_beds: 0
                metric_details:
                  avg_price:
                    status: available
                    reason: null
                    source: HM Land Registry Price Paid Data
                  population_85_plus_pct:
                    status: available
                    reason: null
                    source: ONS Census 2021
                  carehome_demand:
                    status: available
                    reason: null
                    source: PICSy age-based carehome demand model
                    population_projection_year: null
                  existing_beds_all:
                    status: available
                    reason: null
                    source: PICSy published carehome supply and quoted fees
                  existing_beds_ensuite:
                    status: available
                    reason: null
                    source: PICSy published carehome supply and quoted fees
                  existing_beds_wetroom:
                    status: available
                    reason: null
                    source: PICSy published carehome supply and quoted fees
                  undersupply_existing_all:
                    status: available
                    reason: null
                    source: PICSy carehome demand and published bed supply
                    population_projection_year: null
                  undersupply_existing_ensuite:
                    status: available
                    reason: null
                    source: PICSy carehome demand and published bed supply
                    population_projection_year: null
                  undersupply_existing_wetroom:
                    status: available
                    reason: null
                    source: PICSy carehome demand and published bed supply
                    population_projection_year: null
                  bed_weighted_avg_fee_residential_week:
                    status: available
                    reason: null
                    source: PICSy published carehome supply and quoted fees
                    sample_count: 18
                    beds_covered: 895
                  bed_weighted_avg_fee_nursing_week:
                    status: available
                    reason: null
                    source: PICSy published carehome supply and quoted fees
                    sample_count: 12
                    beds_covered: 732
                  planned_permitted_beds:
                    status: available
                    reason: null
                    source: PICSy published care planning pipeline
                  planned_undecided_beds:
                    status: available
                    reason: null
                    source: PICSy published care planning pipeline
                local_authority:
                  requested_area:
                    code: E07000110
                    name: Maidstone
                    kind: lad
                  authority:
                    code: E10000016
                    name: Kent
                    kind: ctyua
                  values:
                    la_avg_fee_residential_week: 1063
                    la_avg_fee_nursing_week: 1240
                    la_occupancy_pct: 88.27
                  metric_details:
                    la_avg_fee_residential_week:
                      status: available
                      reason: null
                      period: 2024-25
                      source: Local authority fee publications
                      source_metadata: null
                      reporting_authority:
                        code: E10000016
                        name: Kent
                        kind: ctyua
                    la_avg_fee_nursing_week:
                      status: available
                      reason: null
                      period: 2024-25
                      source: Local authority fee publications
                      source_metadata: null
                      reporting_authority:
                        code: E10000016
                        name: Kent
                        kind: ctyua
                    la_occupancy_pct:
                      status: available
                      reason: null
                      period: '2026-08-01'
                      source: Capacity Tracker
                      reporting_authority:
                        code: E10000016
                        name: Kent
                        kind: ctyua
                credits:
                  used: 16
                  remaining: 984
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/MetricForbidden'
        '404':
          description: The postcode was not found, or there is no catchment data for it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                request_id: e9eb6345-a86c-44d5-b376-dbff8c0e6726
                error:
                  code: postcode_not_found
                  message: No UK postcode ZZ99 9ZZ was found.
                credits:
                  used: 0
                  remaining: 1000
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
            Cache-Control:
              $ref: '#/components/headers/CacheControl'
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateLimitRemaining'
            X-Credits-Used:
              $ref: '#/components/headers/CreditsUsed'
            X-Credits-Remaining:
              $ref: '#/components/headers/CreditsRemaining'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  headers:
    RequestId:
      description: Identifies the request. Quote it when reporting a problem.
      schema:
        type: string
        format: uuid
    RateLimitLimit:
      description: Requests allowed per minute for this key.
      schema:
        type: integer
    RateLimitRemaining:
      description: Requests left for this key in the current minute.
      schema:
        type: integer
    CreditsUsed:
      schema:
        type: integer
        minimum: 0
        maximum: 50
      description: >-
        Credits used, once authenticated requests reach and complete credit
        accounting.
    CreditsRemaining:
      schema:
        type: integer
        minimum: 0
      description: >-
        Available organisation balance at settlement, excluding outstanding
        holds.
    CacheControl:
      schema:
        type: string
        const: no-store
      description: API JSON responses are not cached.
  schemas:
    CatchmentMetricsResponse:
      type: object
      required:
        - request_id
        - catchment
        - data_version
        - location
        - projection_year
        - values
        - credits
        - metric_details
      properties:
        request_id:
          type: string
          format: uuid
        catchment:
          oneOf:
            - $ref: '#/components/schemas/DriveTimeCatchment'
            - $ref: '#/components/schemas/RadiusCatchment'
        data_version:
          type:
            - string
            - 'null'
          description: >-
            Version of the precomputed demographic catchment. Care supply, fees,
            planning and authority observations are read from their published
            datasets at request time; this version does not identify a
            historical snapshot of those datasets.
        location:
          $ref: '#/components/schemas/Location'
        projection_year:
          type:
            - integer
            - 'null'
          description: >-
            The year population counts were projected to, or null for observed
            values.
        values:
          type: object
          additionalProperties:
            type:
              - number
              - 'null'
          description: >-
            Only requested metrics for this geography. Null means unavailable;
            zero can be a usable value.
        credits:
          $ref: '#/components/schemas/Credits'
        metric_details:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/MetricDetail'
        local_authority:
          $ref: '#/components/schemas/LocalAuthorityResult'
          description: >-
            Included only when at least one local-authority metric is requested.
            These values describe the postcode's reporting authority, not the
            catchment.
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        request_id:
          type: string
          format: uuid
          description: >-
            Present on requests handled by an endpoint. The unknown-path 404
            response has no request ID.
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - area_not_found
                - forbidden
                - internal_error
                - invalid_request
                - not_found
                - outside_coverage
                - postcode_not_found
                - rate_limited
                - unauthorized
                - credits_exhausted
            message:
              type: string
            unknown_metrics:
              type: array
              description: >-
                The metric keys that were not recognised, when that is the
                problem.
              items:
                type: string
            forbidden_metrics:
              type: array
              items:
                type: string
              description: Requested keys without dataset access.
            unsupported_metrics:
              type: array
              items:
                type: string
              description: Requested keys unsupported by this endpoint's geography.
            required_credits:
              type: integer
              minimum: 1
              maximum: 50
              description: >-
                Requested reservation that the available organisation balance
                cannot cover.
        credits:
          $ref: '#/components/schemas/Credits'
    DriveTimeCatchment:
      type: object
      required:
        - type
        - minutes
        - cell_count
      properties:
        type:
          type: string
          const: drive_time
        minutes:
          type: integer
          minimum: 1
          maximum: 25
        cell_count:
          type:
            - integer
            - 'null'
          description: How many grid cells the catchment covers.
    RadiusCatchment:
      type: object
      required:
        - type
        - miles
        - cell_count
      properties:
        type:
          type: string
          const: radius
        miles:
          type: integer
          minimum: 1
          maximum: 10
        cell_count:
          type:
            - integer
            - 'null'
          description: How many grid cells the catchment covers.
    Location:
      type: object
      required:
        - postcode
        - latitude
        - longitude
        - postcode_terminated_on
      properties:
        postcode:
          type: string
          description: The postcode, formatted.
        latitude:
          type: number
          description: Latitude of the postcode centroid.
        longitude:
          type: number
          description: Longitude of the postcode centroid.
        postcode_terminated_on:
          type:
            - string
            - 'null'
          format: date
          description: The date the postcode was retired, or null if it is still in use.
    Credits:
      type: object
      required:
        - used
        - remaining
      properties:
        used:
          type: integer
          minimum: 0
          maximum: 50
          description: >-
            Credits used by this request. One per distinct usable numeric metric
            returned by a successful metric request; zero for free endpoints or
            errors.
        remaining:
          type: integer
          minimum: 0
          description: >-
            Organisation credits available after settlement, excluding other
            in-flight reservations. Shared by all keys in the organisation.
    MetricDetail:
      type: object
      required:
        - status
        - reason
        - source
      properties:
        status:
          type: string
          enum:
            - available
            - unavailable
        reason:
          type:
            - string
            - 'null'
          description: >-
            Explanation when the value is unavailable; null for an available
            value.
        source:
          type:
            - string
            - 'null'
        period:
          type:
            - string
            - 'null'
          description: >-
            Financial year such as 2024-25 for a fee, or ISO month-start date
            such as 2026-08-01 for occupancy. Null if unavailable or outside
            coverage. Catchment details do not include this field.
        reporting_authority:
          anyOf:
            - $ref: '#/components/schemas/Authority'
            - type: 'null'
          description: >-
            Authority whose published figure is returned. May differ from the
            requested district.
        source_metadata:
          type:
            - object
            - 'null'
          additionalProperties: true
          description: >-
            Source-dependent council-fee evidence. May identify sourceKind,
            feeBasis, sourceScope, sourceNationCode, effectivePeriod, sourceUrl,
            nursing contributions and review status. Null when detailed evidence
            is unavailable; do not infer a funding basis.
        sample_count:
          type:
            - number
            - 'null'
          description: Homes with usable private fees for the care type.
        beds_covered:
          type:
            - number
            - 'null'
          description: >-
            Total beds at the homes contributing to that private-fee sample; not
            a count of beds charged this fee.
        population_projection_year:
          type:
            - integer
            - 'null'
          description: >-
            Present on demand and undersupply details: selected projection year,
            or null for source-population demand.
    LocalAuthorityResult:
      type: object
      required:
        - requested_area
        - authority
        - values
        - metric_details
      properties:
        requested_area:
          anyOf:
            - $ref: '#/components/schemas/Authority'
            - type: 'null'
          description: >-
            District containing the postcode, or the direct endpoint's requested
            district/county/unitary authority.
        authority:
          anyOf:
            - $ref: '#/components/schemas/Authority'
            - type: 'null'
          description: >-
            Resolved authority responsible for adult social care. A district
            normally resolves to its parent county; null if none was found for
            the postcode.
        values:
          type: object
          additionalProperties:
            type:
              - number
              - 'null'
          description: >-
            Only requested metrics for this geography. Null means unavailable;
            zero can be a usable value.
        metric_details:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/MetricDetail'
    Authority:
      type: object
      required:
        - code
        - name
        - kind
      properties:
        code:
          type: string
          description: ONS authority code.
        name:
          type: string
        kind:
          type: string
          enum:
            - lad
            - ctyua
          description: District, or county/unitary authority.
  responses:
    InvalidRequest:
      description: >-
        Invalid parameters or unknown/unsupported metric keys.
        error.unknown_metrics and error.unsupported_metrics identify the
        rejected keys.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            unknown:
              value:
                request_id: 6d857aeb-3b97-4e6b-a03f-aa39400d9ed9
                error:
                  code: invalid_request
                  message: >-
                    Unknown metrics: not_a_metric. GET /v1/metrics lists the
                    metrics available.
                  unknown_metrics:
                    - not_a_metric
                credits:
                  used: 0
                  remaining: 974
            unsupported:
              value:
                request_id: f61583ed-950f-4ae8-9fe5-6eb44e389494
                error:
                  code: invalid_request
                  message: >-
                    These metrics do not support this endpoint's geography:
                    la_occupancy_pct. GET /v1/metrics lists supported
                    geographies.
                  unsupported_metrics:
                    - la_occupancy_pct
                credits:
                  used: 0
                  remaining: 974
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
        X-RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        X-Credits-Used:
          $ref: '#/components/headers/CreditsUsed'
        X-Credits-Remaining:
          $ref: '#/components/headers/CreditsRemaining'
    Unauthorized:
      description: The API key is missing, unknown or revoked.
      headers:
        WWW-Authenticate:
          schema:
            type: string
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            request_id: 4bc9eb08-0d69-4c6e-b226-1e66eda03bdc
            error:
              code: unauthorized
              message: >-
                A valid API key is required. Send it as an Authorization: Bearer
                header.
    MetricForbidden:
      description: >-
        Organisation API access is disabled/expired, required metric access is
        absent, or the available credit balance cannot cover the requested
        reservation. credits_exhausted consumes no credits. A valid request
        reserves one credit per unique requested metric before data is read.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            access:
              value:
                request_id: 0e2e47c8-e798-4247-a077-d6b4d66cb70f
                error:
                  code: forbidden
                  message: API access is not enabled for this organisation.
            credits:
              value:
                request_id: e91c7546-82f5-4af6-82de-f48ca6a5a469
                error:
                  code: credits_exhausted
                  message: >-
                    This organisation has insufficient API credits. Contact your
                    administrator for a top-up.
                  required_credits: 1
                credits:
                  used: 0
                  remaining: 0
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
        X-RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        X-Credits-Used:
          $ref: '#/components/headers/CreditsUsed'
        X-Credits-Remaining:
          $ref: '#/components/headers/CreditsRemaining'
    RateLimited:
      description: >-
        Per-key request limit reached in the current fixed calendar-minute
        window. The limit applies to free and metered requests. No credits are
        consumed.
      headers:
        Retry-After:
          description: Seconds until the next minute starts.
          schema:
            type: integer
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            request_id: c4c917f1-4162-47ac-b3d9-1642905491ba
            error:
              code: rate_limited
              message: Rate limit of 60 requests a minute reached.
    InternalError:
      description: >-
        The request or its accounting could not complete. Credits and rate-limit
        headers may be absent when accounting is unavailable. No metric data is
        sent before successful credit settlement.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            accountingFailure:
              summary: Illustrative server failure before credit accounting completes
              value:
                request_id: 9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d
                error:
                  code: internal_error
                  message: >-
                    The request could not be completed. Quote the request id if
                    this keeps happening.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
        X-RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        X-Credits-Used:
          $ref: '#/components/headers/CreditsUsed'
        X-Credits-Remaining:
          $ref: '#/components/headers/CreditsRemaining'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        An API key created under **Account** > **Catchment API**. Keys start
        with `ck_`.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.