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

# Get a signed download URL for the processed file

> Available once `status == "completed"`.

With no query parameters this returns the full processed file, exactly
as it always has. Supply any of them and an export is generated to your
specification and the URL points at that instead — the response shape is
identical either way.




## OpenAPI

````yaml https://api.optimaldial.com/openapi/v1/spec.yaml get /api/v1/uploads/{upload_id}/download/processed
openapi: 3.1.0
info:
  title: OptimalDial API
  version: '2026-08-19'
  summary: Submit phone-number lists, get them processed, receive webhooks.
  description: |
    The OptimalDial REST API lets you programmatically submit lists of phone
    numbers (CSV or JSON, 100–250,000 per request), download processed results,
    and receive HMAC-signed webhooks when uploads change state.

    Map a name column on an upload to enable **OptimalDial Identity**, which
    judges whether each number belongs to the contact named on that row and
    reports it alongside answer intent. Identity is in **public beta** — the
    output format is stable while we tune the thresholds, and feedback is very
    welcome at support@optimaldial.com.

    All endpoints require an API key as `Authorization: Bearer od_live_...`.
    Keys are minted in the in-app developer panel by an organization owner.

    See the human-readable docs at https://docs.optimaldial.com for
    quickstarts, the webhook signature verifier, and the changelog.
  contact:
    name: OptimalDial Support
    email: support@optimaldial.com
    url: https://docs.optimaldial.com
  license:
    name: Proprietary
servers:
  - url: https://api.optimaldial.com
    description: Production
security:
  - bearerAuth: []
tags:
  - name: uploads
    description: Submit, inspect, and download phone-number lists.
  - name: contacts
    description: >
      Single-contact API for per-row enrichment integrations. Available to

      every account with an API key.


      **Use `/api/v2/contacts`** — it mirrors every v1 route and additionally

      reports the nine-tier `OptimalDial_Status` and the OptimalDial Identity

      band.


      `/api/v1/contacts` is **legacy**: supported indefinitely with no removal

      planned, but its `optimaldial_status` reports the Answer Intent value
      only,

      so existing filters keep working untouched. Both versions operate on the

      same contacts — a contact created on either can be read on either, so

      moving to v2 needs no migration.

      Each `standard` contact is charged 1 credit; `max` contacts are billed so

      a batch totals `ceil(1.5 × count)` credits. Result is delivered via

      per-contact callback URL or registered webhook endpoints, and is also

      available via GET.
  - name: webhooks
    description: Register and manage webhook endpoints; inspect delivery history.
  - name: spam
    description: |
      Monitor your outbound numbers for spam/scam-likely flagging across the
      major US carriers (AT&T, T-Mobile, Verizon). Adding a number
      auto-initiates verification — required for the monitoring service
      to place test calls, not a security gate — and once the code is submitted
      OptimalDial re-tests daily, exposing per-carrier status, run history, and
      screenshots. Subscribe to the `spam.detected` and `number.verified`
      webhook events to be notified the moment a number flips to spam.
      Available to every account with an API key and an active subscription.
  - name: credits
    description: |
      Check your organization's current credit balance. Read-only and
      available to every account with an API key.
paths:
  /api/v1/uploads/{upload_id}/download/processed:
    parameters:
      - $ref: '#/components/parameters/UploadId'
    get:
      tags:
        - uploads
      summary: Get a signed download URL for the processed file
      description: |
        Available once `status == "completed"`.

        With no query parameters this returns the full processed file, exactly
        as it always has. Supply any of them and an export is generated to your
        specification and the URL points at that instead — the response shape is
        identical either way.
      operationId: downloadProcessed
      parameters:
        - name: statuses
          in: query
          required: false
          description: >-
            Comma-separated statuses to keep. Accepts tier numbers (`1,3,5`) or
            full values (`Likely Answer`). Omit for every row. An unrecognized
            value returns 400 listing the valid options for that file.
          schema:
            type: string
          example: 1,3,5
        - name: include_answer_intent
          in: query
          required: false
          description: Add the `OptimalDial_Answer_Intent` column.
          schema:
            type: boolean
            default: false
        - name: include_identity
          in: query
          required: false
          description: >-
            Add the `OptimalDial_Identity` column. Empty for lists uploaded
            without name columns.
          schema:
            type: boolean
            default: false
        - name: sort_by_status
          in: query
          required: false
          description: >-
            Order rows best-result-first. Off by default so your original row
            order is preserved unless you ask for it.
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Signed download URL (valid 1 hour).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DownloadUrl'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  parameters:
    UploadId:
      in: path
      name: upload_id
      required: true
      schema:
        type: string
        format: uuid
  schemas:
    DownloadUrl:
      type: object
      required:
        - download_url
        - expires_at
      properties:
        download_url:
          type: string
          format: uri
          description: Signed URL valid for ~1 hour.
        expires_at:
          type: number
          description: Unix timestamp (float seconds) when the signed URL expires.
    ErrorEnvelope:
      type: object
      required:
        - detail
      properties:
        detail:
          oneOf:
            - type: string
            - type: object
  responses:
    Unauthorized:
      description: Missing or invalid API key.
      headers:
        WWW-Authenticate:
          schema:
            type: string
            example: Bearer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    NotFound:
      description: Resource not found, or not visible to this API key's organization.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: od_live_xxxxxxxx
      description: >
        OptimalDial API key, prefixed `od_live_`, sent as `Authorization: Bearer
        ...`.

        Mint keys in the in-app developer panel; they are scoped to a single
        organization.

````