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

# Create a hosted check

> Experimental. Checks the URL over HTTP(S) from Observer's probe locations at the plan's interval and adds it to the organization's first status page (a public page is created when there is none). A URL already watched returns that check with `existing: true`. Only public URLs: internal services, databases and metrics need an Observer Agent. Counts toward the plan's hosted check limit.



## OpenAPI

````yaml api-reference/openapi.json POST /checks
openapi: 3.1.0
info:
  title: Observer API
  version: 1.2.0
  description: >-
    Public API for Observer: read services, metrics, SLOs and SLA statements;
    manage incidents, maintenance windows, manual metric status, config as code
    and Observer Agents. Bearer-auth via API keys (obs_pub_…), scoped per key.
    RFC 7807 problem-detail errors. Cursor pagination. Rate limits are per
    organization. Every date-time value is RFC 3339 in UTC with millisecond
    precision (`2026-01-31T12:00:00.000Z`).
servers:
  - url: https://use.observer/api/v1
security:
  - bearerAuth: []
paths:
  /checks:
    post:
      tags:
        - metrics
      summary: >-
        Watch a public website or API from Observer's own locations and put it
        on a public status page (experimental, nothing to install)
      description: >-
        Experimental. Checks the URL over HTTP(S) from Observer's probe
        locations at the plan's interval and adds it to the organization's first
        status page (a public page is created when there is none). A URL already
        watched returns that check with `existing: true`. Only public URLs:
        internal services, databases and metrics need an Observer Agent. Counts
        toward the plan's hosted check limit.
      operationId: createHostedCheck
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HostedCheckRequest'
            examples:
              url:
                summary: Watch a website
                value:
                  url: https://example.com
              named:
                summary: Named, on a given page
                value:
                  url: api.example.com/health
                  title: API
                  page_id: 0b7e1d2c-3a4f-4b5e-9c6d-7e8f9a0b1c2d
      responses:
        '200':
          description: already watched
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HostedCheck'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Daily-Limit:
              $ref: '#/components/headers/X-RateLimit-Daily-Limit'
            X-RateLimit-Daily-Remaining:
              $ref: '#/components/headers/X-RateLimit-Daily-Remaining'
            X-RateLimit-Daily-Reset:
              $ref: '#/components/headers/X-RateLimit-Daily-Reset'
        '201':
          description: created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HostedCheck'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Daily-Limit:
              $ref: '#/components/headers/X-RateLimit-Daily-Limit'
            X-RateLimit-Daily-Remaining:
              $ref: '#/components/headers/X-RateLimit-Daily-Remaining'
            X-RateLimit-Daily-Reset:
              $ref: '#/components/headers/X-RateLimit-Daily-Reset'
        '400':
          description: >-
            `invalid_json`: the body is not a JSON object. `invalid_url`: not an
            http(s) URL with a full domain. `invalid_title`, `invalid_page_id`,
            `invalid_add_to_page`: wrong type or too long. Other codes come from
            probe validation (for example `host_not_public` for a URL that
            resolves to a private address).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: >-
            `unauthenticated`: no bearer token was sent, or the key is invalid
            or revoked. `detail` distinguishes the two.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: >-
            `forbidden`: the key lacks `write:config`.
            `plan_does_not_permit_api`: the plan does not include the API.
            `quota_exceeded`: the plan's hosted check (or status page) limit is
            reached; `quota` has the numbers (also as top-level `cap` and
            `used`) and `upgrade` the next plan. `feature_locked`: the plan
            includes no hosted checks.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                quota_exceeded:
                  summary: Free plan, fourth hosted check
                  value:
                    type: >-
                      https://docs.use.observer/api/getting-started/errors#quota_exceeded
                    title: quota_exceeded
                    status: 403
                    detail: >-
                      You've reached your plan's hosted check limit (3/3).
                      Upgrade to Starter for more: https://use.observer/pricing
                    capability: outside_in_checks
                    used: 3
                    cap: 3
                    plan: free
                    quota:
                      capability: outside_in_checks
                      used: 3
                      cap: 3
                      plan: free
                    upgrade:
                      plan: starter
                      label: Starter
                      url: https://use.observer/pricing
        '404':
          description: >-
            `page_not_found`: `page_id` is not a status page of this
            organization.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '429':
          description: >-
            `rate_limited`: the organization's per-minute or daily request limit
            is used up (`limit.window` says which). Limits are per organization,
            shared by every key. The response carries `Retry-After` and
            `retry_after`, in seconds.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
          headers:
            Retry-After:
              $ref: '#/components/headers/Retry-After'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Daily-Limit:
              $ref: '#/components/headers/X-RateLimit-Daily-Limit'
            X-RateLimit-Daily-Remaining:
              $ref: '#/components/headers/X-RateLimit-Daily-Remaining'
            X-RateLimit-Daily-Reset:
              $ref: '#/components/headers/X-RateLimit-Daily-Reset'
        '500':
          description: '`internal_error`: an unhandled server error. Safe to retry.'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '503':
          description: >-
            `outside_in_unavailable`: hosted checks are not available right now
            (no probe location is enabled); an Observer Agent can watch the URL
            instead. Nothing was created.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                outside_in_unavailable:
                  value:
                    type: >-
                      https://docs.use.observer/api/getting-started/errors#outside_in_unavailable
                    title: outside_in_unavailable
                    status: 503
                    detail: >-
                      Hosted checks are not available yet. Install the agent to
                      monitor this target.
      security:
        - bearerAuth:
            - write:config
components:
  schemas:
    HostedCheckRequest:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          maxLength: 2048
          description: >-
            The website or endpoint to watch. A bare host (`example.com`) means
            https. It must be reachable from the public internet: internal
            addresses, databases and metrics need an Observer Agent.
        title:
          type: string
          maxLength: 120
          description: Name shown on the status page. Defaults to the host.
        page_id:
          type: string
          format: uuid
          description: >-
            Status page to add the check to. Defaults to the organization's
            first page; a new page is created when it has none.
        add_to_page:
          type: boolean
          default: true
          description: false keeps the check off every status page.
      example:
        url: https://example.com
    HostedCheck:
      type: object
      required:
        - existing
        - check
        - page
        - next
      properties:
        existing:
          type: boolean
          description: >-
            true when the organization already watched this URL; nothing new was
            created.
        experimental:
          type: boolean
          description: 'Always true: hosted checks are an experimental feature.'
        check:
          type: object
          required:
            - id
            - title
            - url
            - locations
          properties:
            id:
              type: string
              format: uuid
              description: The metric id (GET /metrics/{id}).
            title:
              type: string
            url:
              type: string
              format: uri
            interval_minutes:
              type:
                - integer
                - 'null'
              description: Minutes between checks from each location (the plan's minimum).
            locations:
              type: array
              description: Observer's probe locations that run the check.
              items:
                type: object
                required:
                  - id
                  - label
                properties:
                  id:
                    type: string
                  label:
                    type: string
        page:
          type:
            - object
            - 'null'
          description: The status page showing the check, or null with add_to_page=false.
          required:
            - id
            - title
            - subdomain
            - public_url
            - created
          properties:
            id:
              type: string
              format: uuid
            title:
              type: string
            subdomain:
              type: string
            public_url:
              type: string
              format: uri
              description: The status page link.
            created:
              type: boolean
              description: true when this request created the page.
        first_result_eta_seconds:
          type: integer
          description: >-
            Seconds until the first result is expected (0 when the URL was
            already watched). Until then the check reads no data.
        next:
          type: string
          description: What happens next, in one or two sentences.
      example:
        existing: false
        experimental: true
        check:
          id: 6f1c2a3b-4d5e-4f60-8a7b-9c0d1e2f3a4b
          title: example.com
          url: https://example.com/
          interval_minutes: 5
          locations:
            - id: eu-central
              label: Frankfurt, DE
            - id: uk-london
              label: London, GB
        page:
          id: 0b7e1d2c-3a4f-4b5e-9c6d-7e8f9a0b1c2d
          title: Acme status
          subdomain: acme
          public_url: https://acme.use.observer/
          created: true
        first_result_eta_seconds: 90
        next: >-
          The first result is due in about 90 seconds. Then every 5 minutes.
          Until the first result the check shows no data. Hosted checks are
          experimental.
    Problem:
      type: object
      required:
        - type
        - title
        - status
      example:
        type: https://docs.use.observer/api/getting-started/errors#forbidden
        title: forbidden
        status: 403
        detail: 'missing scope: write:incidents'
      properties:
        type:
          type: string
          format: uri
          description: Errors reference URI with the title token as the fragment.
          example: https://docs.use.observer/api/getting-started/errors#forbidden
        title:
          type: string
          description: Stable error token. Branch on this, not on detail.
        status:
          type: integer
        detail:
          type: string
          description: Human-readable explanation. Wording may change.
        retry_after:
          type: integer
          description: >-
            429 only: seconds until the exhausted window resets (mirrors
            Retry-After).
        limit:
          type: object
          description: '429 only: which organization limit was hit.'
          properties:
            scope:
              type: string
              enum:
                - organization
            window:
              type: string
              enum:
                - minute
                - day
            max:
              type: integer
            plan:
              type: string
        errors:
          type: array
          description: >-
            Validation failures (config_invalid, invalid_customer_targeting):
            one entry per problem.
          items:
            type: object
            properties:
              path:
                type: string
              message:
                type: string
        warnings:
          type: array
          description: >-
            config_invalid only: the same non-fatal warnings a successful apply
            returns.
          items:
            type: object
            properties:
              path:
                type: string
              message:
                type: string
        unknown_customers:
          type: array
          description: >-
            unknown_customers only: the submitted values that matched no
            customer in your organization.
          items:
            type: string
        unknown_services:
          type: array
          description: >-
            unknown_services only: the submitted `affected_services` values that
            matched no service in your organization.
          items: {}
        referenced_by:
          type: object
          description: >-
            in_use only: what depends on the object (slos, pages: lists of { id,
            config_key, name }; subscribers: a count).
        quota:
          type: object
          description: >-
            quota_exceeded / feature_locked on a create, item_suspended_plan on
            a write to a suspended item: the plan limit involved.
          properties:
            capability:
              type: string
            used:
              type:
                - integer
                - 'null'
            cap:
              type:
                - integer
                - 'null'
            plan:
              type:
                - string
                - 'null'
        upgrade:
          type: object
          description: >-
            Plan-limit problems only, when a higher plan lifts the limit: the
            smallest such plan and the pricing page.
          properties:
            plan:
              type: string
            label:
              type: string
            url:
              type: string
              format: uri
  headers:
    X-RateLimit-Limit:
      description: Requests allowed per minute for the organization.
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests left in the current minute.
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Seconds until the per-minute window resets.
      schema:
        type: integer
    X-RateLimit-Daily-Limit:
      description: Requests allowed per UTC day for the organization.
      schema:
        type: integer
    X-RateLimit-Daily-Remaining:
      description: Requests left today (UTC).
      schema:
        type: integer
    X-RateLimit-Daily-Reset:
      description: Seconds until the daily quota resets (UTC midnight).
      schema:
        type: integer
    Retry-After:
      description: '429 only: seconds to wait before retrying.'
      schema:
        type: integer
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: obs_pub_
      description: >-
        An organization API key (obs_pub_…) sent as `Authorization: Bearer
        <key>`. Each key carries scopes; an endpoint lists the scope it needs.
        `read:change_events` is reserved: keys can carry it, but no endpoint
        needs it yet.

````

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