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

# Get an application demo's details

> Return the demo record plus the live picture of its namespace on the staging cluster: the derived provisioning steps, the bill of materials, the namespace's Kubernetes events, and the pod/container names that drive the log viewer. A malformed workspace_id is reported as the same 404 as an unknown demo. A browser session twin is mounted at the same path without the /api/v1 prefix (cookie authentication).



## OpenAPI

````yaml https://platform.ankra.app/openapi.json get /api/v1/org/applications/{application_id}/demos/{workspace_id}/detail
openapi: 3.1.0
info:
  title: FastAPI
  version: 0.1.0
servers:
  - url: https://platform.ankra.app
security: []
tags:
  - name: Organisation IAM
    description: >-
      Custom organisation roles and scoped role assignments for member and
      service-account identities.
  - name: Clusters
    description: Create, inspect and manage clusters, and the stacks deployed on them.
  - name: Managed Clusters
    description: Provider-managed control planes, driven through one common surface.
  - name: Imported Clusters
    description: Clusters that already existed and were connected to Ankra.
  - name: Cluster Access
    description: Kubeconfigs, service-account tokens and per-cluster access grants.
  - name: Kubernetes
    description: Read and act on the Kubernetes objects inside a cluster.
  - name: AWS Clusters
    description: >-
      Provision and manage self-managed k3s / kubeadm clusters on AWS EC2 in
      your own VPC.
  - name: Ankra Cloud Clusters
    description: >-
      Provision and manage self-managed kubeadm / k3s clusters on Ankra Cloud
      servers: a private network, a NAT router and a bastion per cluster.
  - name: DigitalOcean Clusters
    description: Provision and manage DigitalOcean Kubernetes clusters.
  - name: Hetzner Clusters
    description: Provision and manage Hetzner Kubernetes clusters.
  - name: OVH Clusters
    description: Provision and manage OVH Kubernetes clusters.
  - name: Scaleway Clusters
    description: Provision and manage Scaleway Kapsule clusters.
  - name: UpCloud Clusters
    description: Provision and manage UpCloud Kubernetes clusters.
  - name: Applications
    description: Deploy, configure and observe applications across the fleet.
  - name: Pipelines
    description: Pipeline definitions and the approval of the authority they declare.
  - name: Backups
    description: >-
      Backup vaults, restore points, protection posture and captures for stacks
      and application deployments; a completed capture is not a verified
      restore.
  - name: Stack Profiles
    description: Reusable stack definitions, their versions and sharing.
  - name: Services
    description: >-
      Versioned service packages and explicit sharing. Runtime admission is
      separate from publication.
  - name: Charts
    description: Browse the chart catalogue behind stacks and addons.
  - name: Helm
    description: Helm registries, credentials and the charts they expose.
  - name: Executions
    description: Long-running platform executions and their jobs.
  - name: Operations
    description: Cancel in-flight cluster operations and their jobs.
  - name: Chat
    description: Conversational sessions, plans and confirmable actions.
  - name: AI Management
    description: >-
      Customer agent lifecycle, authenticated identity and organisation
      automation controls.
  - name: AI Agent Runs
    description: Autonomous agent runs and their outcomes.
  - name: AI Tickets
    description: The AI ticket board, its sync connections and settings.
  - name: AI Playbooks
    description: Reusable playbooks the AI lanes execute.
  - name: AI Conditions
    description: Conditions that gate AI autonomy.
  - name: AI Remediation
    description: >-
      The organisation's auto-remediation policy: what the AI lanes may fix by
      themselves, and who approves the rest.
  - name: AI Engineering Handoffs
    description: Work the AI lanes escalate to a human engineer.
  - name: AI Environment
    description: The environment and base stacks AI demos deploy into.
  - name: Security
    description: Findings, advisories, SBOMs, compliance and posture.
  - name: Cost
    description: Cluster and fleet cost, rate cards and cost settings.
  - name: Decisions
    description: >-
      The decision ledger behind the Security and Cost queues: proposals a
      surface computed, the approve and set-aside decisions people took on them,
      and the receipts of running them.
  - name: Billing
    description: Subscription and spend caps.
  - name: Organisation
    description: Members, invitations, audit logs and organisation settings.
  - name: Account Tokens
    description: Personal access tokens for the API and CLI.
  - name: Credentials
    description: The shared credential store.
  - name: AWS Credentials
    description: >-
      AWS credentials: access keys or CloudFormation-onboarded STS roles for
      cost, EKS and self-managed provisioning.
  - name: Ankra Cloud Credentials
    description: >-
      Ankra Cloud API tokens, shared by the self-managed and managed Ankra Cloud
      lanes.
  - name: Azure Credentials
    description: Azure credentials and SSH keys.
  - name: DigitalOcean Credentials
    description: DigitalOcean credentials and SSH keys.
  - name: Hetzner Credentials
    description: Hetzner credentials and SSH keys.
  - name: OVH Credentials
    description: OVH credentials and SSH keys.
  - name: Scaleway Credentials
    description: Scaleway credentials.
  - name: UpCloud Credentials
    description: UpCloud credentials and SSH keys.
  - name: Data Source Credentials
    description: Credentials for metrics and log sources.
  - name: DNS Credentials
    description: Credentials for DNS providers.
  - name: Object Storage Buckets
    description: >-
      Buckets Ankra creates and manages on an organisation's own provider
      credentials.
  - name: DNS
    description: DNS zones and records, including custom organisation zones.
  - name: Cloudflare
    description: Cloudflare domains and the credentials behind them.
  - name: Variables
    description: Organisation- and cluster-scoped variables.
  - name: SOPS
    description: Encrypt and decrypt values with the organisation SOPS config.
  - name: Alerts
    description: Alert integrations and ingest credentials.
  - name: Notifications
    description: Notification routes and their delivery targets.
  - name: Support
    description: Support tickets.
  - name: AI Settings
    description: Organisation AI provider, model catalog and per-function model settings
paths:
  /api/v1/org/applications/{application_id}/demos/{workspace_id}/detail:
    get:
      tags:
        - Applications
      summary: Get an application demo's details
      description: >-
        Return the demo record plus the live picture of its namespace on the
        staging cluster: the derived provisioning steps, the bill of materials,
        the namespace's Kubernetes events, and the pod/container names that
        drive the log viewer. A malformed workspace_id is reported as the same
        404 as an unknown demo. A browser session twin is mounted at the same
        path without the /api/v1 prefix (cookie authentication).
      operationId: >-
        get_application_demo_detail_api_v1_org_applications__application_id__demos__workspace_id__detail_get
      parameters:
        - in: path
          name: application_id
          required: true
          schema:
            type: string
            title: Application Id
        - in: path
          name: workspace_id
          required: true
          schema:
            format: uuid
            type: string
            title: Workspace Id
        - in: header
          name: authorization
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: Authorization
        - in: header
          name: x-ankra-organisation-id
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: X-Ankra-Organisation-Id
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApplicationDemoDetailResponse'
          description: Successful Response
        '401':
          description: Unauthorized
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DemoDetailError'
          description: Not found ("Unknown demo for this application")
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
          description: Validation Error
components:
  schemas:
    ApplicationDemoDetailResponse:
      description: >-
        The demo record plus the live picture of its namespace on the staging
        cluster.
      properties:
        can_deploy:
          type: boolean
        demo:
          $ref: '#/components/schemas/DemoWorkspace'
        inspection:
          $ref: '#/components/schemas/DemoInspection'
        staging:
          $ref: '#/components/schemas/DemoStagingStatus'
      required:
        - demo
        - inspection
        - staging
        - can_deploy
      type: object
    DemoDetailError:
      description: >-
        The FastAPI-style detail envelope the demo routes use for
        400/403/404/409/502 responses.
      properties:
        detail:
          type: string
      required:
        - detail
      type: object
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          title: Detail
          type: array
      title: HTTPValidationError
      type: object
    DemoWorkspace:
      description: >-
        One ephemeral PR or branch demo record. kind is pr_demo or branch_demo;
        status is one of pending, provisioning, ready, failed, tearing_down,
        destroyed.
      properties:
        application_id:
          anyOf:
            - type: string
            - type: 'null'
        branch:
          anyOf:
            - type: string
            - type: 'null'
        cluster_id:
          anyOf:
            - type: string
            - type: 'null'
        component:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            The deployable component this demo runs; null for rows predating
            component records.
        container_port:
          anyOf:
            - type: integer
            - type: 'null'
        created_at:
          type: string
          format: date-time
        created_by_user_id:
          type: string
        database:
          type: boolean
        detected_container_port:
          anyOf:
            - type: integer
            - type: 'null'
          description: >-
            The port the readiness reconciler's log parser saw the container
            announce; set with port_corrected_at when a runtime correction
            happened.
        port_corrected_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          description: >-
            When the demo's container port was automatically corrected from the
            container's own logs; a demo row receives at most one correction.
        demo_base_stack_error:
          anyOf:
            - type: string
            - type: 'null'
        demo_base_stack_id:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            References the shared base stack this demo depends on;
            name/status/error are joined from the base stack for display. All
            absent when the demo has no base-stack dependency.
        demo_base_stack_name:
          anyOf:
            - type: string
            - type: 'null'
        demo_base_stack_status:
          anyOf:
            - type: string
            - type: 'null'
        demo_stack_error:
          anyOf:
            - type: string
            - type: 'null'
        demo_stack_name:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            The stack-profile replica attached to a full-stack demo; absent for
            single-service demos (as are demo_stack_status and
            demo_stack_error).
        demo_stack_status:
          anyOf:
            - type: string
            - type: 'null'
        environment:
          description: >-
            The demo's env entry names and secret flags only - values (sentinel
            or plaintext) never ride list surfaces.
          items:
            $ref: '#/components/schemas/DemoEnvironmentSummaryEntry'
          type: array
        expires_at:
          type: string
          format: date-time
        head_sha:
          anyOf:
            - type: string
            - type: 'null'
        id:
          type: string
        image_tag:
          anyOf:
            - type: string
            - type: 'null'
        kind:
          type: string
        last_error:
          anyOf:
            - type: string
            - type: 'null'
        namespace:
          type: string
        pod_name:
          anyOf:
            - type: string
            - type: 'null'
        pr_number:
          anyOf:
            - type: integer
            - type: 'null'
        preview_url:
          anyOf:
            - type: string
            - type: 'null'
        preview_dns_unconfirmed_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          description: >-
            Stamped when the demo was published ready although a successful DNS
            probe at that moment still found nothing behind the preview
            hostname: the URL had not resolved as of this time. Absent is no
            adverse claim, never a confirmation that the URL works.
        repos:
          items:
            $ref: '#/components/schemas/DemoWorkspaceRepo'
          type: array
        stack_profile_name:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            The profile's display name, denormalized so list surfaces can badge
            full-stack demos without a second lookup.
        status:
          type: string
        provisioning_deadline_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          description: >-
            The instant the readiness reconciler gives up on a
            still-provisioning demo and marks it failed. An absolute deadline
            rather than the timestamp it derives from, so the only guarantee
            that matters stays true however that timestamp is resolved. It is
            measured from provisioning_started_at - the phase log's record of
            when this run began - which is the same instant the reconciler
            enforces it from. It used to be measured from
            ai_workspaces.updated_at on both sides, a row-last-written clock
            rather than a status one, so a stack replica settling or a port
            correction landing pushed the deadline out by a further full window.
            Present only while the demo status is provisioning - that is the
            reconciler own WHERE clause, and no deadline is enforced against a
            demo in any other state. Absent otherwise (and on surfaces that do
            not resolve it); a consumer without it must show no time estimate
            rather than falling back to created_at.
        provisioning_prediction:
          anyOf:
            - $ref: '#/components/schemas/DemoProvisioningPrediction'
            - type: 'null'
          description: >-
            How long this demo is actually expected to take, and the evidence
            behind it. This is the figure to show a starting demo and the
            fraction to draw its progress bar as; provisioning_timeout_seconds
            is a give-up threshold and rendering it as the expected wait
            overstates a sub-minute demo by an order of magnitude. Null when the
            history is too thin to draw a prediction from, which is a real
            answer and not an error: a consumer must then show the demo as
            starting with no estimate rather than falling back to the timeout.
        provisioning_started_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          description: >-
            When the demo entered its CURRENT provisioning run, from the demo
            phase log. Elapsed time is measured from here rather than from
            provisioning_deadline_at minus provisioning_timeout_seconds: the
            deadline counts from ai_workspaces.updated_at, which the stack
            sub-state rewrites mid-run, so on a full-stack demo the two diverge
            the moment its stack settles. Present only while the demo is
            provisioning.
        provisioning_timeout_seconds:
          type: integer
          description: >-
            The width of the provisioning window ending at
            provisioning_deadline_at, so a consumer can render
            elapsed-against-budget directly; wider for a demo carrying a stack
            replica or waiting on a deploying base stack. Present only alongside
            provisioning_deadline_at, i.e. only while the demo is provisioning.
        components:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/DemoWorkspaceComponent'
          description: >-
            Every deployable component the demo runs; null for single-workload
            demos predating multi-component records.
      required:
        - id
        - kind
        - application_id
        - cluster_id
        - namespace
        - pod_name
        - pr_number
        - branch
        - image_tag
        - container_port
        - preview_url
        - head_sha
        - status
        - last_error
        - repos
        - database
        - expires_at
        - created_by_user_id
        - created_at
      type: object
    DemoInspection:
      description: >-
        The full live picture of one demo, read from the staging cluster in one
        uncached pass. cluster_reachable false means the staging cluster or its
        agent could not be reached; steps and resources are then empty rather
        than misleadingly showing nothing-has-happened-yet.
      properties:
        cluster_reachable:
          type: boolean
        containers:
          type: array
          items:
            type: string
        elapsed_seconds:
          description: Time in the demo's current status.
          type: integer
        events:
          items:
            $ref: '#/components/schemas/DemoEvent'
          type: array
        pod_names:
          type: array
          items:
            type: string
        resources:
          items:
            $ref: '#/components/schemas/DemoResource'
          type: array
        steps:
          items:
            $ref: '#/components/schemas/DemoStep'
          type: array
        timeout_seconds:
          description: The provisioning budget after which the reconciler fails the demo.
          type: integer
        unreachable_reason:
          type: string
        unreadable_kinds:
          description: >-
            Resource kinds the cluster agent could not read on this pass; absent
            from resources because their state is unknown, not because they do
            not exist.
          items:
            type: string
          type: array
      required:
        - cluster_reachable
        - unreachable_reason
        - steps
        - resources
        - events
        - pod_names
        - containers
        - unreadable_kinds
        - elapsed_seconds
        - timeout_seconds
      type: object
    DemoStagingStatus:
      description: The staging-cluster status the demos tab renders.
      properties:
        agent_online:
          type: boolean
        cluster_id:
          anyOf:
            - type: string
            - type: 'null'
        cluster_name:
          anyOf:
            - type: string
            - type: 'null'
        configured:
          type: boolean
      required:
        - configured
        - cluster_id
        - cluster_name
        - agent_online
      type: object
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          title: Location
          type: array
        msg:
          title: Message
          type: string
        type:
          title: Error Type
          type: string
      required:
        - loc
        - msg
        - type
      title: ValidationError
      type: object
    DemoEnvironmentSummaryEntry:
      description: >-
        The value-free projection list surfaces expose: names and secret flags
        only, never values.
      properties:
        name:
          type: string
        secret:
          type: boolean
      required:
        - name
        - secret
      type: object
    DemoWorkspaceRepo:
      description: One repository cloned into a workspace pod.
      properties:
        name:
          type: string
        path:
          type: string
        url:
          type: string
      required:
        - name
        - url
        - path
      type: object
    DemoProvisioningPrediction:
      properties:
        typical_seconds:
          type: integer
          description: >-
            The median run: half of comparable demos were live by this many
            seconds after starting. This is the expected wait, and the number a
            starting demo should be shown against - not
            provisioning_timeout_seconds, which is when Ankra gives up.
        slow_seconds:
          type: integer
          description: >-
            The 90th percentile run. A demo past typical_seconds is not late;
            one past this is unusual. The gap between the two is the estimate
            own spread, and a consumer should render it as such rather than as a
            countdown that has run out.
        samples:
          type: integer
          description: >-
            How many completed runs the percentiles were drawn from. Always at
            least the configured floor (AI_DEMO_PREDICTION_MIN_SAMPLES, default
            5); below it no prediction is emitted at all.
        basis:
          type: string
          enum:
            - application
            - organisation
          description: >-
            Which history the numbers came from. application means this
            application own past demos of the same kind and dependency shape -
            the better predictor, preferred whenever it clears the sample floor.
            organisation means the wider organisation history for that shape.
      required:
        - typical_seconds
        - slow_seconds
        - samples
        - basis
      title: DemoProvisioningPrediction
      type: object
      description: >-
        How long comparable demos actually took, measured from the demo phase
        log (ai_workspace_phase_events). Comparable means the same demo kind and
        the same dependency shape at start - whether it carries its own stack
        replica, and whether the shared base stack was already warm - because a
        demo landing on a warm base stack is live in under a minute while the
        same demo landing on a cold one waits out a Helm install, and a figure
        averaging the two describes neither.
    DemoWorkspaceComponent:
      type: object
      description: >-
        One deployable component of a demo: its own Deployment and Service
        inside the demo namespace. The entry component owns the demo host's root
        path.
      properties:
        name:
          type: string
        image_tag:
          type: string
        container_port:
          type: integer
        ingress_path:
          type: string
          description: >-
            Path prefix the component is published under on the demo host; empty
            keeps it in-cluster only.
        entry:
          type: boolean
        detected_container_port:
          type: integer
          description: >-
            The port this component's container announced in its own logs; set
            with port_corrected_at when a runtime correction repointed its
            workload.
        port_corrected_at:
          type: string
          format: date-time
          description: >-
            When this component's container port was automatically corrected
            from its own logs; each component receives at most one correction.
            The entry component mirrors the demo row's port_corrected_at.
      required:
        - name
        - container_port
    DemoEvent:
      description: One Kubernetes event from the demo namespace.
      properties:
        count:
          type: integer
        message:
          type: string
        object:
          type: string
        reason:
          type: string
        timestamp:
          type: string
        type:
          type: string
      required:
        - type
        - reason
        - message
        - object
        - count
        - timestamp
      type: object
    DemoResource:
      description: >-
        One entry in a demo's bill of materials: a resource Ankra creates (or
        that Kubernetes derives from one), paired with what the cluster
        currently holds.
      properties:
        ankra:
          description: Whether Ankra itself applies this resource.
          type: boolean
        facts:
          items:
            $ref: '#/components/schemas/DemoResourceFact'
          type: array
        kind:
          type: string
        manifest:
          description: >-
            The live object when present (pruned of Kubernetes bookkeeping and
            with every secret value redacted), otherwise the manifest Ankra
            would apply. manifest_source says which.
          type: object
        manifest_source:
          type: string
        name:
          type: string
        present:
          description: Whether the object exists on the cluster right now.
          type: boolean
        purpose:
          type: string
        status:
          enum:
            - ready
            - pending
            - missing
            - failed
          type: string
        component:
          type: string
          description: >-
            Demo component this resource belongs to; empty for demo-wide
            infrastructure.
      required:
        - kind
        - name
        - purpose
        - ankra
        - present
        - status
        - facts
        - manifest
        - manifest_source
      type: object
    DemoStep:
      description: >-
        One stage of bringing a demo up. Every 'done' is backed by a live
        cluster signal; nothing is inferred from elapsed time. Keys are stable
        across releases: namespace, guardrails, base_stack (only for demos with
        a base-stack dependency), stack (only for full-stack demos), workload,
        scheduled, image, accepting, routing.
      properties:
        detail:
          description: >-
            The live evidence behind status - a node name, a pull reason, an
            ingress address.
          type: string
        key:
          enum:
            - namespace
            - guardrails
            - base_stack
            - stack
            - workload
            - scheduled
            - image
            - accepting
            - routing
          type: string
        label:
          type: string
        status:
          description: >-
            pending: not started, or not yet observable; active: currently being
            waited on; done: positively observed as complete; failed: cannot
            recover without redeploying; skipped: does not apply to this demo.
          enum:
            - pending
            - active
            - done
            - failed
            - skipped
          type: string
      required:
        - key
        - label
        - status
        - detail
      type: object
    DemoResourceFact:
      description: One labelled observation about a resource, rendered verbatim.
      properties:
        label:
          type: string
        value:
          type: string
      required:
        - label
        - value
      type: object

````