Mission Test Configs

    Save a mission-test setup once and re-run it on demand. Configs hold sector, mission, acceptance, and profile id. Launch a run from a saved config with POST /testing/mission-test-configs/{id}/runs. Check a config before saving it, search saved configs, and create many at once from a CSV or Excel sheet.

    15 endpoints

    Create a mission test config

    POST/testing/mission-test-configs

    Save a reusable mission-test config. Configs hold sector, mission, acceptance, and profile id, and can be re-launched on demand.

    Body Parameters

    NameTypeRequiredDescription
    namestringrequiredDisplay name for the config
    sectorstringrequiredSector key from the catalogue
    missionstringrequiredThe objective the agent should pursue on the call
    acceptancestringrequiredAcceptance criteria used to grade the run
    profileIdstringrequiredProfile id supplying caller identity and phone number
    languagestringoptionalLanguage every run of this config is held in, e.g. es, fr, or multi for a call that switches language. Listed in full under Language codes on the Mission Tests page — any other value is rejected with a 400. Omit it and runs are held in English. These are the mission-test call languages, not the wider regional transcription codes used by standard tests and mapping: en-GB is rejected here
    tagsstring[]optionalUp to 10 lowercase kebab-case tags (1-32 chars, pattern ^[a-z0-9][a-z0-9-]*$) for filtering and organisation

    Request

    bash
    curl -X POST -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name":"Banking password reset","sector":"banking","mission":"Reset my online banking password","acceptance":"Agent verifies identity and resets password","profileId":"prof_xyz789"}' \
      https://api.nopaque.co.uk/testing/mission-test-configs

    Response

    json
    {
      "id": "mtc_abc123",
      "name": "Banking password reset",
      "sector": "banking",
      "mission": "Reset my online banking password",
      "acceptance": "Agent verifies identity and resets password",
      "profileId": "prof_xyz789",
      "tags": [
        "banking"
      ],
      "createdAt": "2026-05-06T12: 00: 00Z"
    }

    List mission test configs

    GET/testing/mission-test-configs

    Every saved mission-test config in the workspace, in full, in one response. This route takes no query parameters and ignores any you send, so it does not filter or page. To search by name, phone number, sector, profile, tag or creation time, sort, or page, use Find mission test configs (`GET /mission-test-configs`). The SDKs' `list` method calls this route, so filters passed to it are ignored too; use curl against Find mission test configs for now.

    Request

    bash
    curl -H "x-api-key: YOUR_API_KEY" \
      https://api.nopaque.co.uk/testing/mission-test-configs

    Response

    json
    {
      "configs": [
        {
          "id": "mtc_abc123",
          "workspaceId": "ws_abc123",
          "name": "Banking password reset",
          "sector": "banking",
          "mission": "Reset my online banking password",
          "acceptance": "Agent verifies identity and resets password",
          "phoneNumber": "+441234567890",
          "profileId": "prof_xyz789",
          "tags": [
            "banking"
          ],
          "createdAt": "2026-05-06T12: 00: 00Z",
          "updatedAt": "2026-05-06T12: 00: 00Z"
        }
      ]
    }

    Get a mission test config

    GET/testing/mission-test-configs/{id}

    Get a single saved mission-test config by id.

    Path Parameters

    NameTypeRequiredDescription
    idstringrequiredMission-test config id

    Request

    bash
    curl -H "x-api-key: YOUR_API_KEY" \
      https://api.nopaque.co.uk/testing/mission-test-configs/mtc_abc123

    Response

    json
    {
      "id": "mtc_abc123",
      "name": "Banking password reset",
      "sector": "banking",
      "mission": "Reset my online banking password",
      "acceptance": "Agent verifies identity and resets password",
      "profileId": "prof_xyz789",
      "tags": [
        "banking"
      ],
      "createdAt": "2026-05-06T12: 00: 00Z"
    }

    Update a mission test config

    PATCH/testing/mission-test-configs/{id}

    Partially update a saved mission-test config. Send only the fields you want to change. At least one field is required. Pass null for description or tags to clear them.

    Path Parameters

    NameTypeRequiredDescription
    idstringrequiredMission-test config id

    Body Parameters

    NameTypeRequiredDescription
    namestringoptionalUpdated display name
    descriptionstring | nulloptionalUpdated description. Pass null to clear it
    phoneNumberstringoptionalUpdated phone number in E.164 format
    sectorstringoptionalUpdated sector key
    missionstringoptionalUpdated mission objective
    acceptancestringoptionalUpdated acceptance criteria
    profileIdstringoptionalUpdated profile id
    languagestring | nulloptionalUpdated call language, e.g. es, fr, or multi. Listed in full under Language codes on the Mission Tests page — any other value is rejected with a 400. Omit it and the saved language is left unchanged; pass null to put the config back to English. Not the transcription codes used by standard tests and mapping: en-GB is rejected here
    tagsstring[] | nulloptionalReplace the tag list. Pass null to clear all tags. Up to 10 lowercase kebab-case tags (1-32 chars)

    Request

    bash
    curl -X PATCH -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name":"Banking password reset (EU)","tags":["banking","eu"]}' \
      https://api.nopaque.co.uk/testing/mission-test-configs/mtc_abc123

    Response

    json
    {
      "id": "mtc_abc123",
      "name": "Banking password reset (EU)",
      "sector": "banking",
      "mission": "Reset my online banking password",
      "acceptance": "Agent verifies identity and resets password",
      "profileId": "prof_xyz789",
      "tags": [
        "banking",
        "eu"
      ],
      "updatedAt": "2026-05-06T12: 10: 00Z"
    }

    Delete a mission test config

    DELETE/testing/mission-test-configs/{id}

    Delete a saved mission-test config.

    Path Parameters

    NameTypeRequiredDescription
    idstringrequiredMission-test config id

    Request

    bash
    curl -X DELETE -H "x-api-key: YOUR_API_KEY" \
      https://api.nopaque.co.uk/testing/mission-test-configs/mtc_abc123

    Response

    json
    {
      "message": "Mission test config deleted successfully"
    }

    Run a saved mission test

    POST/testing/mission-test-configs/{id}/runs

    Launch a new mission test run from a saved config. Returns the new MissionTestRun.

    Path Parameters

    NameTypeRequiredDescription
    idstringrequiredMission-test config id

    Request

    bash
    curl -X POST -H "x-api-key: YOUR_API_KEY" \
      https://api.nopaque.co.uk/testing/mission-test-configs/mtc_abc123/runs

    Response

    json
    {
      "id": "mtr_abc123",
      "kind": "freeform",
      "configId": "mtc_abc123",
      "sector": "banking",
      "mission": "Reset my online banking password",
      "acceptance": "Agent verifies identity and resets password",
      "profile": {
        "phoneNumber": "+441234567890"
      },
      "status": "queued",
      "createdAt": "2026-05-06T12: 00: 00Z"
    }

    Find mission test configs

    GET/mission-test-configs

    Search the saved mission-test configs, with filters, sorting and cursor paging. Items are slim: they leave out the long mission and acceptance text, which Get a mission test config returns. Filters combine. Keep paging with `cursor` until `nextCursor` is absent. This is the route the MCP tool `listMissionTestConfigs` calls. Note the path: no `/testing` prefix.

    Query Parameters

    NameTypeRequiredDescription
    namestringoptionalConfigs whose name contains this text. Case-sensitive: "test mission" does not match "Test Mission"
    phoneNumberstringoptionalConfigs that call this number. E.164, exact match, e.g. +441234567890
    sectorstringoptionalConfigs in this sector, exact match
    profileIdstringoptionalConfigs that use this profile
    tagstringoptionalConfigs carrying this tag. One tag, lowercase, exact match
    createdAfterstringoptionalISO8601 date-time. Only configs created after it
    createdBeforestringoptionalISO8601 date-time. Only configs created before it
    sortstringoptionalcreatedAt (default) or name
    sortDirstringoptionalasc or desc (default desc)
    limitnumberoptionalConfigs per page, 1-100 (default 50)
    cursorstringoptionalnextCursor from the previous response

    Request

    bash
    curl -H "x-api-key: YOUR_API_KEY" \
      "https://api.nopaque.co.uk/mission-test-configs?sector=banking&tag=banking&limit=50"

    Response

    json
    {
      "configs": [
        {
          "id": "mtc_abc123",
          "workspaceId": "ws_abc123",
          "name": "Banking password reset",
          "phoneNumber": "+441234567890",
          "sector": "banking",
          "profileId": "prof_xyz789",
          "tags": [
            "banking"
          ],
          "createdAt": "2026-05-06T12: 00: 00Z",
          "updatedAt": "2026-05-06T12: 00: 00Z"
        }
      ],
      "nextCursor": "eyJpZCI6Im10Y19hYmMxMjMifQ"
    }

    Check a new config without saving it

    POST/testing/mission-test-configs/draft

    Check a new mission-test config exactly as Create a mission test config would, and report every problem at once instead of stopping at the first. Nothing is saved and nothing changes, so it is safe to call as often as you like. The body is the create body. Problems cover each field that fails validation, a phone number the dial policy refuses (field `phoneNumber`), and a `profileId` that is not in your workspace. A body whose fields fail is still a 200, with the failures in `problems`; 400 only when the body is not a JSON object. 503 when the dial policy could not be reached.

    Body Parameters

    NameTypeRequiredDescription
    ...objectrequiredThe same fields as Create a mission test config

    Request

    bash
    curl -X POST -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name":"Banking password reset","sector":"banking","mission":"Reset my online banking password","acceptance":"Agent verifies identity and resets password","phoneNumber":"+441234567890","profileId":"prof_missing"}' \
      https://api.nopaque.co.uk/testing/mission-test-configs/draft

    Response

    json
    {
      "config": {
        "name": "Banking password reset",
        "sector": "banking",
        "mission": "Reset my online banking password",
        "acceptance": "Agent verifies identity and resets password",
        "phoneNumber": "+441234567890",
        "profileId": "prof_missing"
      },
      "problems": [
        {
          "field": "profileId",
          "message": "This caller persona no longer exists."
        }
      ]
    }

    Check up to 25 new configs without saving them

    POST/testing/mission-test-configs/draft-batch

    Check each draft exactly as Check a new config without saving it would, and answer one result per draft, in the order sent. Nothing is saved. A draft that is not an object gets the problem "Each draft must be an object." rather than failing the call. 400 when `drafts` is missing, empty or longer than 25.

    Body Parameters

    NameTypeRequiredDescription
    draftsobject[]required1-25 new configs, each the same shape as the create body

    Request

    bash
    curl -X POST -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"drafts":[{"name":"Store 1","sector":"retail","mission":"Ask for opening hours","acceptance":"Agent gives opening hours","phoneNumber":"+441234567890","profileId":"prof_xyz789"}]}' \
      https://api.nopaque.co.uk/testing/mission-test-configs/draft-batch

    Response

    json
    {
      "results": [
        {
          "config": {
            "name": "Store 1",
            "sector": "retail",
            "mission": "Ask for opening hours",
            "acceptance": "Agent gives opening hours",
            "phoneNumber": "+441234567890",
            "profileId": "prof_xyz789"
          },
          "problems": []
        }
      ]
    }

    Check a change to a config without saving it

    POST/testing/mission-test-configs/{id}/draft

    Check a change exactly as Update a mission test config would, and report every problem at once. Nothing is saved. The body is the PATCH body. The answer carries the config as it would be after the change, the fields that would differ (`changes`), and the config's current `updatedAt` as `version`. To save, send the same body to Update a mission test config with `?expectedUpdatedAt=<version>`, so the save is refused if the config changed in between.

    Path Parameters

    NameTypeRequiredDescription
    idstringrequiredMission-test config id

    Body Parameters

    NameTypeRequiredDescription
    ...objectrequiredThe same fields as Update a mission test config

    Request

    bash
    curl -X POST -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name":"Banking password reset (EU)"}' \
      https://api.nopaque.co.uk/testing/mission-test-configs/mtc_abc123/draft

    Response

    json
    {
      "config": {
        "id": "mtc_abc123",
        "workspaceId": "ws_abc123",
        "name": "Banking password reset (EU)",
        "sector": "banking",
        "mission": "Reset my online banking password",
        "acceptance": "Agent verifies identity and resets password",
        "phoneNumber": "+441234567890",
        "profileId": "prof_xyz789",
        "tags": [
          "banking"
        ],
        "createdAt": "2026-05-06T12: 00: 00Z",
        "updatedAt": "2026-05-06T12: 00: 00Z"
      },
      "problems": [],
      "changes": [
        {
          "field": "name",
          "before": "Banking password reset",
          "after": "Banking password reset (EU)"
        }
      ],
      "version": "2026-05-06T12: 00: 00Z"
    }

    Start a sheet import

    POST/imports

    Create many mission-test configs from a CSV or .xlsx sheet. This call records the upload and returns a presigned `PUT` URL, valid for 300 seconds. Upload the bytes with the same `Content-Type` and `Content-Length`, then call Get a sheet import: the first read after the upload parses the file. At most 5 MB, 10 sheets, 2,000 rows per sheet and 5,000 rows in all. An import and its file are kept for 30 days. Then: read rows with Read a sheet's rows, map each row to a config, check them with Check up to 25 new configs without saving them, and save them with Commit a sheet import.

    Body Parameters

    NameTypeRequiredDescription
    fileNamestringrequirede.g. stores.xlsx
    contentTypestringrequiredtext/csv or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    sizeBytesnumberrequiredThe file's exact size. The upload URL is signed for it

    Request

    bash
    # 1. Start the import
    curl -X POST -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"fileName":"stores.csv","contentType":"text/csv","sizeBytes":18234}' \
      https://api.nopaque.co.uk/imports
    
    # 2. Upload the file to uploadUrl from the response
    curl -X PUT -H "Content-Type: text/csv" \
      --data-binary @stores.csv \
      "UPLOAD_URL"

    Response

    json
    {
      "import": {
        "id": "3f9c2a1e-7b4d-4e8a-9c1f-5d6e7a8b9c0d",
        "fileName": "stores.csv",
        "status": "awaiting_upload",
        "createdAt": "2026-11-12T10: 00: 00Z",
        "expiresAt": "2026-12-12T10: 00: 00Z"
      },
      "uploadUrl": "https://<bucket>.s3.eu-west-2.amazonaws.com/imports/<workspaceId>/3f9c2a1e-7b4d-4e8a-9c1f-5d6e7a8b9c0d/stores.csv?X-Amz-Signature=...",
      "uploadExpiresAt": "2026-11-12T10: 05: 00Z"
    }

    Get a sheet import

    GET/imports/{id}

    Get the import. While it is `awaiting_upload` and the file has arrived, this call reads the file once: the import becomes `ready`, with each sheet's headers, row count and first five rows, or `unreadable` with a `problem` in plain words. Every cell is a string; dates are `YYYY-MM-DD`. While a commit or undo runs, `commit` or `undo` shows its progress. Statuses: `awaiting_upload`, `ready`, `unreadable`, `committing`, `committed`, `commit_failed`, `undoing`, `undone`.

    Path Parameters

    NameTypeRequiredDescription
    idstringrequiredImport id, from Start a sheet import

    Request

    bash
    curl -H "x-api-key: YOUR_API_KEY" \
      https://api.nopaque.co.uk/imports/3f9c2a1e-7b4d-4e8a-9c1f-5d6e7a8b9c0d

    Response

    json
    {
      "import": {
        "id": "3f9c2a1e-7b4d-4e8a-9c1f-5d6e7a8b9c0d",
        "fileName": "stores.csv",
        "status": "ready",
        "createdAt": "2026-11-12T10: 00: 00Z",
        "expiresAt": "2026-12-12T10: 00: 00Z",
        "sheets": [
          {
            "name": "Stores",
            "headers": [
              "Store",
              "Phone"
            ],
            "rowCount": 120,
            "firstRows": [
              {
                "Store": "Leeds",
                "Phone": "+441134960000"
              },
              {
                "Store": "York",
                "Phone": "+441904960000"
              }
            ]
          }
        ]
      }
    }

    Read a sheet's rows

    GET/imports/{id}/rows

    Up to 50 data rows of one sheet, each keyed by header, with its 0-based index. Only once the import is `ready` or later; 409 with code `IMPORT_NOT_READY` before that (call Get a sheet import first).

    Path Parameters

    NameTypeRequiredDescription
    idstringrequiredImport id, from Start a sheet import

    Query Parameters

    NameTypeRequiredDescription
    sheetstringoptionalThe sheet's name. Defaults to the first sheet
    fromnumberoptionalIndex of the first row to return (default 0)
    countnumberoptionalHow many rows, at most 50 (default 25)

    Request

    bash
    curl -H "x-api-key: YOUR_API_KEY" \
      "https://api.nopaque.co.uk/imports/3f9c2a1e-7b4d-4e8a-9c1f-5d6e7a8b9c0d/rows?sheet=Stores&from=0&count=50"

    Response

    json
    {
      "sheet": "Stores",
      "from": 0,
      "total": 120,
      "rows": [
        {
          "index": 0,
          "cells": {
            "Store": "Leeds",
            "Phone": "+441134960000"
          }
        },
        {
          "index": 1,
          "cells": {
            "Store": "York",
            "Phone": "+441904960000"
          }
        }
      ]
    }

    Commit a sheet import

    POST/imports/{id}/commit

    Create up to 1,000 mission-test configs in the background, each checked exactly as Create a mission test config checks it and each tagged with `tag`. Returns 202 at once with the import `committing`; poll Get a sheet import for `commit.created` of `commit.total` until it is `committed` (or `commit_failed`). A test that fails its checks is listed in `commit.failures` and the rest are still created. Only from `ready`, and only once (409 `IMPORT_ALREADY_COMMITTED` after that). Creating configs places no calls.

    Path Parameters

    NameTypeRequiredDescription
    idstringrequiredImport id, from Start a sheet import

    Body Parameters

    NameTypeRequiredDescription
    tagstringrequiredimport- followed by 6 lowercase letters or digits, e.g. import-ab12cd. Added to every config, so the set can be found and undone together
    testsobject[]requiredThe configs to create, each the same shape as the create body

    Request

    bash
    curl -X POST -H "x-api-key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"tag":"import-ab12cd","tests":[{"name":"Leeds","sector":"retail","mission":"Ask for opening hours","acceptance":"Agent gives opening hours","phoneNumber":"+441134960000","profileId":"prof_xyz789"}]}' \
      https://api.nopaque.co.uk/imports/3f9c2a1e-7b4d-4e8a-9c1f-5d6e7a8b9c0d/commit

    Response

    json
    {
      "import": {
        "id": "3f9c2a1e-7b4d-4e8a-9c1f-5d6e7a8b9c0d",
        "fileName": "stores.csv",
        "status": "committing",
        "createdAt": "2026-11-12T10: 00: 00Z",
        "expiresAt": "2026-12-12T10: 00: 00Z",
        "sheets": [
          {
            "name": "Stores",
            "headers": [
              "Store",
              "Phone"
            ],
            "rowCount": 120,
            "firstRows": [
              {
                "Store": "Leeds",
                "Phone": "+441134960000"
              },
              {
                "Store": "York",
                "Phone": "+441904960000"
              }
            ]
          }
        ],
        "commit": {
          "tag": "import-ab12cd",
          "total": 120,
          "created": 0,
          "failed": 0,
          "failures": []
        }
      }
    }

    Undo a sheet import

    POST/imports/{id}/undo

    Delete, in the background, every config the commit created, unless it has been changed since: a changed config, or one already deleted, is kept and listed in `undo.keptIds`. Returns 202 at once with the import `undoing`; poll Get a sheet import until it is `undone`. Allowed from `committed`, or from `commit_failed` (a commit that stopped part-way still created configs, and all of them are undone). If the undo stops early, the import goes back to the status it came from with a `problem`, and the undo can be asked for again. No body.

    Path Parameters

    NameTypeRequiredDescription
    idstringrequiredImport id, from Start a sheet import

    Request

    bash
    curl -X POST -H "x-api-key: YOUR_API_KEY" \
      https://api.nopaque.co.uk/imports/3f9c2a1e-7b4d-4e8a-9c1f-5d6e7a8b9c0d/undo

    Response

    json
    {
      "import": {
        "id": "3f9c2a1e-7b4d-4e8a-9c1f-5d6e7a8b9c0d",
        "fileName": "stores.csv",
        "status": "undoing",
        "createdAt": "2026-11-12T10: 00: 00Z",
        "expiresAt": "2026-12-12T10: 00: 00Z",
        "sheets": [
          {
            "name": "Stores",
            "headers": [
              "Store",
              "Phone"
            ],
            "rowCount": 120,
            "firstRows": [
              {
                "Store": "Leeds",
                "Phone": "+441134960000"
              },
              {
                "Store": "York",
                "Phone": "+441904960000"
              }
            ]
          }
        ],
        "commit": {
          "tag": "import-ab12cd",
          "total": 120,
          "created": 120,
          "failed": 0,
          "failures": []
        },
        "undo": {
          "total": 120,
          "deleted": 0,
          "kept": 0,
          "keptIds": []
        }
      }
    }