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

# Retrieve a report

> The hiring report: a ship score and verdict band, the four scored areas, the evidence behind them, suggested interview questions, and the candidate’s rank in your pipeline.

Before grading finishes the endpoint answers 200 with `evaluated: false` and null scores rather than 404 — poll it, or watch the submission status.

A pillar's `score` is `null` when there wasn't enough evidence to report one, and `low_confidence` marks a score built on thin evidence. Render both as "not enough data", never as a zero.

`not_assessed` lists, in plain language, anything the challenge brief gave the candidate no way to demonstrate. Those areas are excluded from scoring entirely rather than scored low.

`percentile` is omitted until we hold enough comparable attempts for it to mean something. `pipeline_rank` compares the candidate against your own applicants and is always present once evaluated.



## OpenAPI

````yaml /api-reference/openapi.json get /api/v1/submissions/{id}/report
openapi: 3.1.0
info:
  title: Dotportion API
  version: 1.0.0
  description: >-
    Create assessments, invite candidates, and pull back hiring reports.


    Authenticate with an API key as a bearer token. Keys are scoped to a single
    organization and cannot reach another one. Use a `sk_test_` key to develop
    against deterministic sample data.
servers:
  - url: https://app.dotportion.com
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Challenges
    description: The challenge library available to you.
  - name: Assessments
    description: Job postings built from a challenge.
  - name: Invitations
    description: Candidate invitations and their lifecycle.
  - name: Submissions
    description: Candidate attempts, reports and event logs.
  - name: Members
    description: Your organization’s team.
  - name: Account
    description: Plan, usage and branding.
paths:
  /api/v1/submissions/{id}/report:
    get:
      tags:
        - Submissions
      summary: Retrieve a report
      description: >-
        The hiring report: a ship score and verdict band, the four scored areas,
        the evidence behind them, suggested interview questions, and the
        candidate’s rank in your pipeline.


        Before grading finishes the endpoint answers 200 with `evaluated: false`
        and null scores rather than 404 — poll it, or watch the submission
        status.


        A pillar's `score` is `null` when there wasn't enough evidence to report
        one, and `low_confidence` marks a score built on thin evidence. Render
        both as "not enough data", never as a zero.


        `not_assessed` lists, in plain language, anything the challenge brief
        gave the candidate no way to demonstrate. Those areas are excluded from
        scoring entirely rather than scored low.


        `percentile` is omitted until we hold enough comparable attempts for it
        to mean something. `pipeline_rank` compares the candidate against your
        own applicants and is always present once evaluated.
      operationId: getReport
      parameters:
        - name: id
          in: path
          required: true
          description: The submission id.
          schema:
            type: string
            format: uuid
        - name: format
          in: query
          required: false
          description: >-
            Response format. `pdf` is accepted by the schema but not implemented
            yet.
          schema:
            type: string
            enum:
              - json
              - pdf
            default: json
      responses:
        '200':
          description: Success.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  submission_id: 00000000-0000-4000-8000-000000000031
                  status: evaluated
                  evaluated: true
                  ship_score: 87
                  verdict: strong_yes
                  verdict_label: Strong yes
                  confidence: low
                  summary: ''
                  scored_as_role: null
                  pillars:
                    - id: correctness
                      label: Correctness
                      score: 89
                      low_confidence: false
                      summary: ''
                      not_assessed: []
                    - id: craft
                      label: Craft
                      score: 77
                      low_confidence: false
                      summary: ''
                      not_assessed: []
                    - id: ai_fluency
                      label: AI Fluency
                      score: 75
                      low_confidence: false
                      summary: ''
                      not_assessed: []
                    - id: rigor
                      label: Rigor
                      score: 89
                      low_confidence: false
                      summary: ''
                      not_assessed: []
                  strengths: []
                  flags: []
                  interview_questions: []
                  facts:
                    time_used_minutes: null
                    time_allotted_minutes: 60
                    budget_used_dollars: 1.25
                    budget_allotted_dollars: 3
                    ai_authored_pct: null
                    churn_pct: null
                    ai_exchange_count: 0
                  scope_exclusions: []
                  integrity_status: flagged
                  pipeline_rank:
                    rank: 2
                    total: 9
                  tasks: []
                  generated_at: '2026-01-15T12:00:00.000Z'
                meta:
                  request_id: req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c
        '400':
          description: >-
            INVALID_INPUT — You asked for `format=pdf`, which is not
            implemented.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                error:
                  code: INVALID_INPUT
                  message: Invalid request
                  details:
                    formErrors: []
                    fieldErrors:
                      name:
                        - String must contain at least 1 character(s)
                  request_id: req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c
        '401':
          description: INVALID_TOKEN — The key is missing, malformed, revoked, or expired.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                error:
                  code: INVALID_TOKEN
                  message: Invalid or revoked API key
                  request_id: req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c
        '403':
          description: >-
            INSUFFICIENT_SCOPE — The key doesn't carry the scope this endpoint
            needs.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                error:
                  code: INSUFFICIENT_SCOPE
                  message: 'This API key lacks the required scope: write.'
                  request_id: req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c
        '404':
          description: >-
            NOT_FOUND — No such resource, it belongs to another organization, or
            the id isn't a UUID — all indistinguishable by design.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                error:
                  code: NOT_FOUND
                  message: Resource not found
                  request_id: req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c
        '429':
          description: RATE_LIMITED — The key exhausted its hourly quota for this class.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                error:
                  code: RATE_LIMITED
                  message: >-
                    Rate limit exceeded for write requests (200/hour). Retry
                    after 2026-01-15T13:00:00.000Z.
                  details:
                    limit: 200
                    remaining: 0
                    reset: 1768482000
                  request_id: req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c
        '500':
          description: INTERNAL_ERROR — Something failed on our side. Quote the request_id.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                error:
                  code: INTERNAL_ERROR
                  message: Internal server error
                  request_id: req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c
      security:
        - bearerAuth: []
components:
  headers:
    XRequestId:
      description: Correlation id for this request. Quote it in support requests.
      schema:
        type: string
    XRateLimitLimit:
      description: Requests permitted per hour for this quota class.
      schema:
        type: integer
    XRateLimitRemaining:
      description: Requests left in the current window.
      schema:
        type: integer
    XRateLimitReset:
      description: Unix time (seconds) when the window resets.
      schema:
        type: integer
    RetryAfter:
      description: Seconds to wait before retrying. Present on 429.
      schema:
        type: integer
  schemas:
    SuccessEnvelope:
      type: object
      description: >-
        Every successful response. `meta` carries the request id and any
        pagination.
      properties:
        data:
          description: The resource, or an array of them.
          oneOf:
            - type: object
            - type: array
              items:
                type: object
        meta:
          $ref: '#/components/schemas/Meta'
      required:
        - data
        - meta
    ErrorEnvelope:
      type: object
      description: Every failure. Switch on `error.code`, not on the message.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - INVALID_INPUT
                - INVALID_TOKEN
                - PLAN_LIMIT_REACHED
                - INSUFFICIENT_SCOPE
                - NOT_FOUND
                - CONFLICT
                - RATE_LIMITED
                - INTERNAL_ERROR
              description: Stable machine-readable code.
            message:
              type: string
              description: Human-readable. May be reworded.
            details:
              description: Field-level validation errors, when applicable.
            request_id:
              type: string
          required:
            - code
            - message
            - request_id
      required:
        - error
    Meta:
      type: object
      properties:
        request_id:
          type: string
          description: Correlation id for this request.
        page:
          type: integer
          description: 'Offset pagination: current page.'
        page_size:
          type: integer
          description: 'Offset pagination: page size.'
        total:
          type: integer
          description: 'Offset pagination: total matching records.'
        has_more:
          type: boolean
          description: Whether another page exists.
        next_cursor:
          type:
            - string
            - 'null'
          description: >-
            Cursor pagination: pass as `cursor` for the next page. `null` means
            the end. Opaque — never construct one.
      required:
        - request_id
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your API key, live (`sk_live_…`) or test (`sk_test_…`). Create one in
        Settings → API keys. Send it as `Authorization: Bearer <key>` — never in
        a query string.

````