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

# Set an app's policy layers

> Replaces the app's active layers, whole and in order, and publishes them into its policy: devices take them at their next fetch (spec 12.4). An entry without an id is a new layer; one with an active layer's id edits it. An id of a layer no longer active is 409 layer_stopped (it was stopped, rolled back or removed since the caller read it); an id the app never had is 400. An active layer left out is removed and kept in the history. At most 50. Owners and admins; audited as instrumentation.layers_update.



## OpenAPI

````yaml /api-reference/openapi.json put /orgs/{orgId}/projects/{projectId}/apps/{appId}/layers
openapi: 3.1.0
info:
  title: Apsio API
  version: 0.1.0
  description: >-
    Read API v0: your projects, release health and comparisons, missing symbols,
    issues, sessions, vitals, cohort comparisons, performance (app start,
    screens, hangs, MetricKit) and network endpoints and traces for one project.
    Authenticate with a project token as a bearer token, with an OAuth access
    token from Apsio's authorization server (MCP clients), or, from the console,
    with the session cookie of a member of the project's organization.
servers:
  - url: https://api.apsio.io/v1
security: []
paths:
  /orgs/{orgId}/projects/{projectId}/apps/{appId}/layers:
    put:
      summary: Set an app's policy layers
      description: >-
        Replaces the app's active layers, whole and in order, and publishes them
        into its policy: devices take them at their next fetch (spec 12.4). An
        entry without an id is a new layer; one with an active layer's id edits
        it. An id of a layer no longer active is 409 layer_stopped (it was
        stopped, rolled back or removed since the caller read it); an id the app
        never had is 400. An active layer left out is removed and kept in the
        history. At most 50. Owners and admins; audited as
        instrumentation.layers_update.
      parameters:
        - schema:
            type: string
            pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
            example: 0192f3a4-0000-7000-8000-00000000a001
          required: true
          name: orgId
          in: path
        - schema:
            type: string
            pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
            example: 0192f3a4-0000-7000-8000-00000000a001
          required: true
          name: projectId
          in: path
        - schema:
            type: string
            pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
            example: 0192f3a4-0000-7000-8000-00000000a001
          required: true
          name: appId
          in: path
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                layers:
                  type: array
                  items:
                    $ref: '#/components/schemas/LayerInput'
                  maxItems: 50
              required:
                - layers
      responses:
        '200':
          description: The layers, as published
          content:
            application/json:
              schema:
                type: object
                properties:
                  layers:
                    type: array
                    items:
                      $ref: '#/components/schemas/Layer'
                required:
                  - layers
      security:
        - session: []
components:
  schemas:
    LayerInput:
      type: object
      properties:
        id:
          type: string
          description: >-
            Left out: a new layer. An active layer's id: an edit of it. A layer
            no longer active: 409 layer_stopped.
        name:
          type: string
          minLength: 1
          maxLength: 80
        when:
          $ref: '#/components/schemas/LayerWhen'
        rollout:
          type:
            - object
            - 'null'
          properties:
            percent:
              type: number
              minimum: 0
              maximum: 100
            holdback_percent:
              type: number
              minimum: 0
              maximum: 50
          required:
            - percent
        expires_at:
          type:
            - string
            - 'null'
          format: date-time
        changes:
          $ref: '#/components/schemas/LayerChanges'
        guardrails:
          $ref: '#/components/schemas/LayerGuardrails'
      required:
        - name
    Layer:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        when:
          $ref: '#/components/schemas/LayerTargets'
        hints:
          type: object
          properties:
            installs:
              type: array
              items:
                type: string
            users:
              type: array
              items:
                type: string
          required:
            - installs
            - users
          description: >-
            The last four characters of each install and app user the layer
            targets: read only. Leave when.installs and when.users out of a PUT
            to keep them; send them only to target new ones.
        rollout:
          $ref: '#/components/schemas/LayerRollout'
        expires_at:
          type:
            - string
            - 'null'
        changes:
          $ref: '#/components/schemas/LayerChanges'
        guardrails:
          $ref: '#/components/schemas/LayerGuardrails'
        state:
          type: string
          enum:
            - active
            - stopped
            - rolled_back
            - removed
            - expired
          description: >-
            active: published. stopped: a person stopped it (stopped_reason says
            why). rolled_back: a guardrail did (stopped_reason says which
            bound). removed: left out of the list. expired: past expires_at.
        stopped_reason:
          type:
            - string
            - 'null'
        stopped_at:
          type:
            - string
            - 'null'
        updated_by:
          type:
            - string
            - 'null'
        updated_at:
          type: string
      required:
        - id
        - name
        - when
        - hints
        - rollout
        - expires_at
        - changes
        - guardrails
        - state
        - stopped_reason
        - stopped_at
        - updated_by
        - updated_at
    LayerWhen:
      type: object
      properties:
        app_version:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 256
          maxItems: 100
        os_name:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 256
          maxItems: 20
        os_version_min:
          type: string
          minLength: 1
          maxLength: 32
        os_version_max:
          type: string
          minLength: 1
          maxLength: 32
        device_model:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 256
          maxItems: 100
        installs:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 256
          maxItems: 100
          description: >-
            Install ids (app.installation.id). Written plain, stored only as
            spec 12.4's match hashes; read back as their last four characters.
            Left out on an edit: the layer keeps the ones it targets.
        users:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 256
          maxItems: 100
          description: >-
            App users (user.hash), as installs are: plain on write, the last
            four characters when read. A layer matched by a user hash applies
            only while the app has set it.
      description: >-
        The devices a layer targets (spec 12.4); each key narrows it, and a
        layer without one targets every device. Installs and users together: at
        most 100.
    LayerChanges:
      type: object
      properties:
        capture:
          type: object
          additionalProperties: {}
        instrumentation:
          type: object
          properties:
            families:
              type: object
              properties:
                summary:
                  $ref: '#/components/schemas/InstrumentationFamily'
                errors:
                  $ref: '#/components/schemas/InstrumentationFamily'
                logs:
                  $ref: '#/components/schemas/InstrumentationFamily'
                spans:
                  $ref: '#/components/schemas/InstrumentationFamily'
                network:
                  $ref: '#/components/schemas/InstrumentationFamily'
                metrics:
                  $ref: '#/components/schemas/InstrumentationFamily'
                replay:
                  $ref: '#/components/schemas/InstrumentationFamily'
                resources:
                  $ref: '#/components/schemas/InstrumentationFamily'
              additionalProperties: false
              description: >-
                A family left out is in always mode, except resources, which is
                in never mode (D113).
          required:
            - families
        replay:
          type: object
          additionalProperties: {}
        masking:
          type: object
          additionalProperties: {}
      description: >-
        What the layer changes, as the policy's own keys (spec 12.2): capture
        only narrows, masking and replay only tighten, and in instrumentation
        only the families: a family is replaced whole, and may list only the
        app's rules.
    LayerGuardrails:
      type: object
      properties:
        crash_free_drop_points:
          type: number
          exclusiveMinimum: 0
          maximum: 100
          description: >-
            Roll the layer back when the applied devices' crash-free sessions
            fall this many points below the holdback's.
        ingest_increase_pct:
          type: number
          exclusiveMinimum: 0
          maximum: 1000
          description: >-
            Roll the layer back when the applied devices' ingest per session is
            this many percent above the holdback's.
        min_sessions:
          type: integer
          minimum: 50
          maximum: 1000000
          description: 'Sessions each group needs before a bound is checked: 200 by default.'
      description: >-
        The bounds the backend watches (spec 12.4): past one, it publishes the
        policy without the layer and marks it rolled_back. A guardrail needs a
        holdback.
    LayerTargets:
      type: object
      properties:
        app_version:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 256
          maxItems: 100
        os_name:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 256
          maxItems: 20
        os_version_min:
          type: string
          minLength: 1
          maxLength: 32
        os_version_max:
          type: string
          minLength: 1
          maxLength: 32
        device_model:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 256
          maxItems: 100
      description: >-
        What a layer targets besides installs and app users (spec 12.4). Sent
        back as read, it changes nothing; the targeted installs and users are in
        the layer's hints.
    LayerRollout:
      type:
        - object
        - 'null'
      properties:
        percent:
          type: number
          minimum: 0
          maximum: 100
        holdback_percent:
          type: number
          minimum: 0
          maximum: 50
      required:
        - percent
        - holdback_percent
      description: >-
        A staged rollout (spec 12.4), with at most two decimals: percent of the
        targeted installs take the layer, holdback_percent are kept out of it to
        compare against; together at most 100.
    InstrumentationFamily:
      type: object
      properties:
        mode:
          type: string
          enum:
            - always
            - sampled
            - on_trigger
            - never
        rate:
          type: number
          minimum: 0
          maximum: 1
        triggers:
          type: array
          items:
            $ref: '#/components/schemas/InstrumentationTrigger'
        window_minutes:
          type: integer
          minimum: 1
          maximum: 60
        retention_hours:
          type: integer
          minimum: 1
          maximum: 168
          description: >-
            This family's retention on the device, instead of the store's (spec
            15.6).
        cap_bytes:
          type: integer
          minimum: 65536
          maximum: 20971520
          description: The most bytes of the store this family takes (spec 15.6).
      required:
        - mode
      description: >-
        A family's mode (spec 15.3): always; sampled at a rate; on_trigger with
        triggers and window_minutes; or never. A sampled family may list
        triggers too: a session outside its sample sends the window before a
        trigger.
    InstrumentationTrigger:
      anyOf:
        - type: string
        - type: object
          properties:
            trigger:
              type: string
            window_minutes:
              type: integer
              minimum: 1
              maximum: 60
            after:
              type: string
              enum:
                - session
                - window
          required:
            - trigger
      description: >-
        A trigger's name (crash, error, anr, rage_tap, dead_tap, event:<name>,
        rule:<id>), or an object that sets its own window and whether the rest
        of the session is released after it (after: session) or only the window
        (after: window) (spec 15.4).
  securitySchemes:
    session:
      type: apiKey
      in: cookie
      name: apsio_session
      description: >-
        The console session, set by /v1/auth/callback (`__Host-apsio_session`
        when host-only).

````

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