---
title: "List Tests and observed conversion event choices"
method: GET
path: "/agent/workspaces/{workspace}/tests"
tags: ["AdTestApi"]
---

# List Tests and observed conversion event choices

`GET /agent/workspaces/{workspace}/tests`

## Request

- Base URL: `https://plainrouter.com/api/v1`
- URL: `https://plainrouter.com/api/v1/agent/workspaces/{workspace}/tests`
- Auth: HTTP bearer

Lists scoped Tests, their loser pause candidate status and reasons, and observed conversion event choices with last-30-day recorded counts.

## Path parameters

- `workspace` integer, required

## Query parameters

- `per_page` integer
- `page` integer

## Response `200`

Tests and observed conversion event choices.

- AdTestListRead
  - `tests` object, required
    - `current_page` integer, required
    - `data` object[], required
      - `id` string, required
      - `workspace_id` integer, required
      - `platform_ad_account_id` integer, required
      - `ad_set_id` string, required
      - `axis` 'hook' | 'angle' | 'visual' | 'offer' | 'format' | 'landing', required
      - `event_name` string, nullable, required: Legacy explicit event name; null for workspace-default mode.
      - `conversion_definition_version` 1 | 2, required
      - `conversion_events` string[], required: Immutable canonical choices. Version 1 exposes its original event choice.
      - `exclude_subscription_payments` boolean, required: Subscription-payment exclusion captured at creation; false for version 1.
      - `arrivals_floor` integer, required
      - `count_health_click_threshold` integer, nullable: Link-click threshold frozen at conclusion; null until concluded or for legacy Tests.
      - `minimum_conversions` integer, required
      - `maximum_days` integer, required
      - `maximum_spend_minor` string, nullable, required: Optional maximum in positive whole Meta minor units, using the same unit scale as Launch plan budget_amount_minor.
      - `anomaly_threshold_percent` string, required
      - `first_day` string, date, required
      - `timezone` string, required
      - `currency` string, required
      - `created_at` string, date-time, nullable, required
      - `members` object[], required
        - `ad_id` string, required
        - `position` integer, required
        - `baseline_host` string, nullable: Immutable normalized landing host once the member has a baseline.
        - `baseline_path` string, nullable: Immutable normalized landing path once the member has a baseline.
      - `pause_proposals` object[], required
        - `ad_id` string, required
        - `status` 'pending' | 'proposed' | 'skipped' | 'expired', required
        - `reason` 'already_paused' | 'deleted' | 'archived' | 'campaign_paused' | 'adset_paused' | 'decision_window_elapsed' | 'null', nullable, required: Stable reason code when the proposal was skipped or expired.
        - `decision_deadline_at` string, date-time, required: Immutable deadline 24 hours after the Test's candidates are created on the database clock.
      - `verdict` object, nullable, required
        - `outcome` 'winner' | 'no_clear_winner' | 'not_judged' | 'halted' | 'null', nullable, required
        - `winner_ad_id` string, nullable, required
        - `reason` string, nullable, required
        - `halt_details` object, nullable
          - `ad_id` string
          - `effective_status` 'DISAPPROVED' | 'WITH_ISSUES'
          - `date` string, date
          - `link_clicks` integer
          - `counted_arrivals` integer
          - `ad_test_member_id` string
          - `baseline` object
            - `host` string, required
            - `path` string, required
          - `observed_destinations` object[]
            - `host` string, required
            - `path` string, required
            - `counted_arrivals` integer, required
        - `window_start` string, date, nullable, required
        - `window_end` string, date, nullable, required
        - `concluded_at` string, date-time, nullable, required
        - `members` object[], required
          - `ad_id` string, required
          - `state` 'not_delivered' | 'insufficient' | 'ranked' | 'facts_unavailable' | 'halted', required
          - `rank` integer, nullable, required
          - `spend` string, nullable, required
          - `impressions` integer, nullable, required
          - `counted_arrivals` integer, nullable, required
          - `recorded_conversions` integer, nullable, required: PlainRouter recorded conversions under this Test’s frozen definition. Version 1 retains its original recorded-count semantics.
          - `admitted_conversions` integer, nullable, required: Admitted conversions are shown beside recorded conversions and are never substituted for them.
          - `spend_per_recorded_conversion` string, nullable, required: Major-unit spend divided by PlainRouter recorded conversions; used only to compare members within this Test.
          - `covered_days` string[], required
        - `daily_facts` object[], required
          - `date` string, date, required
          - `ad_test_member_id` string, required
          - `ad_id` string, required
          - `spend_minor` string, required: Exact spend in Meta minor units for the account currency, including any stored fractional component.
          - `spend` string, nullable, required: Account-currency spend in major units.
          - `impressions` integer, nullable, required
          - `inline_link_clicks` integer, nullable
          - `counted_arrivals` integer, nullable, required
          - `recorded_conversions` integer, nullable, required
          - `admitted_conversions` integer, nullable, required
    - `first_page_url` string, nullable, required
    - `from` integer, nullable, required
    - `last_page` integer, required
    - `last_page_url` string, nullable, required
    - `links` object[], required
      - `active` boolean, required
      - `label` string, required
      - `url` string, nullable, required
    - `next_page_url` string, nullable, required
    - `path` string, required
    - `per_page` integer, required
    - `prev_page_url` string, nullable, required
    - `to` integer, nullable, required
    - `total` integer, required
  - `observed_conversion_events_available` boolean, required
  - `observed_conversion_events` object[], required
    - `event_name` string, required
    - `recorded_count` integer, required

## Other responses

- `401`: An active workspace principal is required; credential refusals include an error code and description.
- `403`: The workspace principal lacks a matching plan grant or account binding.
- `404`: The scoped workspace, account, or Test is unavailable, or the API route is not found.
- `422`: Request validation failed, the event is not in the observed list, or selected ads are not members of the ad set.
- `429`: The shared API rate limit was exceeded; Retry-After gives the seconds until another request is allowed.

---

[API](https://skmtc.dev/plainrouter/apis/plainrouter-conversion-api.md) · [All operations](https://skmtc.dev/plainrouter/apis/plainrouter-conversion-api/llms.txt) · [OpenAPI document](https://skmtc.dev/plainrouter/apis/plainrouter-conversion-api/revisions/d071d4f4f05c?raw)
