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

# Add criteria

> Attach default or custom criteria to a test set.

Adds one or more criteria to a test set. Send either a `defaultCriterionId` or a full custom criterion definition.

## Headers

<ParamField header="Authorization" type="string" required>
  Bearer token containing your Fini workspace API key. Format: `Bearer fini_...` The key needs `write` scope.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  `application/json`
</ParamField>

## Path parameters

<ParamField path="testSetId" type="string" required>
  Test set ID.
</ParamField>

## Body parameters

<ParamField body="criteria" type="array" required>
  One or more criteria to attach to the test set.
</ParamField>

<ParamField body="criteria[].defaultCriterionId" type="string">
  Default criterion ID from [Get fields context](/en/api-reference/get-test-set-fields-context). When this is present, do not send custom definition fields; the API copies the default's definition.
</ParamField>

<ParamField body="criteria[].name" type="string">
  Required for custom criteria.
</ParamField>

<ParamField body="criteria[].type" type="string">
  Required for custom criteria. Use `deterministic`, `basic_judge`, or `complex_judge`.
</ParamField>

<ParamField body="criteria[].judgePrompt" type="string">
  Required for `basic_judge` and `complex_judge` criteria.
</ParamField>

<ParamField body="criteria[].passPrompt" type="string">
  Required for `basic_judge` and `complex_judge` criteria.
</ParamField>

<ParamField body="criteria[].failPrompt" type="string">
  Required for `basic_judge` and `complex_judge` criteria.
</ParamField>

<ParamField body="criteria[].condition" type="object">
  Required for `deterministic` criteria. Judge criteria cannot include a condition.
</ParamField>

<ParamField body="criteria[].blocking" type="boolean" default="false">
  Whether failing this criterion should fail the conversation overall.
</ParamField>

## Response

Returns the test set's updated criteria array.

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api-prod.usefini.com/v2/test-sets/44c1f705-8e1a-4f61-8c4c-d519d37fb6b7/criteria/public' \
    --header 'Authorization: Bearer fini_your_api_key' \
    --header 'Content-Type: application/json' \
    --data '{
      "criteria": [
        {
          "defaultCriterionId": "96eab02d-3bc3-4b90-ae5b-1a41a1444afa",
          "blocking": true
        },
        {
          "name": "Used a public reply",
          "type": "deterministic",
          "condition": {
            "scope": "ARRAY",
            "array": {
              "path": "replyTypes",
              "itemType": "string"
            },
            "quantifier": "ANY",
            "predicate": {
              "left": {
                "path": "replyTypes",
                "dataType": "array"
              },
              "operator": "contains",
              "right": {
                "value": "message"
              }
            }
          },
          "blocking": false
        }
      ]
    }'
  ```

  ```javascript Node.js theme={null}
  const testSetId = '44c1f705-8e1a-4f61-8c4c-d519d37fb6b7';

  const response = await fetch(`https://api-prod.usefini.com/v2/test-sets/${testSetId}/criteria/public`, {
    method: 'POST',
    headers: {
      Authorization: 'Bearer fini_your_api_key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      criteria: [
        {
          defaultCriterionId: '96eab02d-3bc3-4b90-ae5b-1a41a1444afa',
          blocking: true
        },
        {
          name: 'Used a public reply',
          type: 'deterministic',
          condition: {
            scope: 'ARRAY',
            array: {
              path: 'replyTypes',
              itemType: 'string'
            },
            quantifier: 'ANY',
            predicate: {
              left: {
                path: 'replyTypes',
                dataType: 'array'
              },
              operator: 'contains',
              right: {
                value: 'message'
              }
            }
          },
          blocking: false
        }
      ]
    })
  });

  const criteria = await response.json();
  ```

  ```python Python theme={null}
  import requests

  test_set_id = "44c1f705-8e1a-4f61-8c4c-d519d37fb6b7"

  response = requests.post(
      f"https://api-prod.usefini.com/v2/test-sets/{test_set_id}/criteria/public",
      headers={
          "Authorization": "Bearer fini_your_api_key",
          "Content-Type": "application/json",
      },
      json={
          "criteria": [
              {
                  "defaultCriterionId": "96eab02d-3bc3-4b90-ae5b-1a41a1444afa",
                  "blocking": True,
              },
              {
                  "name": "Used a public reply",
                  "type": "deterministic",
                  "condition": {
                      "scope": "ARRAY",
                      "array": {
                          "path": "replyTypes",
                          "itemType": "string",
                      },
                      "quantifier": "ANY",
                      "predicate": {
                          "left": {
                              "path": "replyTypes",
                              "dataType": "array",
                          },
                          "operator": "contains",
                          "right": {
                              "value": "message",
                          },
                      },
                  },
                  "blocking": False,
              },
          ],
      },
  )

  criteria = response.json()
  ```
</RequestExample>

<ResponseExample>
  ```json 201 Created theme={null}
  [
    {
      "id": "96eab02d-3bc3-4b90-ae5b-1a41a1444afa",
      "testSetId": "44c1f705-8e1a-4f61-8c4c-d519d37fb6b7",
      "companyId": "1d2a4c9f-59f8-4f9c-bd36-6f12e0d5d927",
      "defaultCriterionId": "96eab02d-3bc3-4b90-ae5b-1a41a1444afa",
      "name": "Goal resolution",
      "type": "complex_judge",
      "judgePrompt": "Judge whether the conversation resolved the user's goal.",
      "passPrompt": "The user's goal was resolved.",
      "failPrompt": "The user's goal was not resolved.",
      "condition": null,
      "blocking": true,
      "isActive": true,
      "createdAt": "2026-07-28T08:56:12.000Z",
      "updatedAt": "2026-07-28T08:56:12.000Z"
    },
    {
      "id": "1e149042-74c6-446a-9da0-e48036909aa9",
      "testSetId": "44c1f705-8e1a-4f61-8c4c-d519d37fb6b7",
      "companyId": "1d2a4c9f-59f8-4f9c-bd36-6f12e0d5d927",
      "defaultCriterionId": null,
      "name": "Used a public reply",
      "type": "deterministic",
      "judgePrompt": null,
      "passPrompt": null,
      "failPrompt": null,
      "condition": {
        "scope": "ARRAY",
        "array": {
          "path": "replyTypes",
          "itemType": "string"
        },
        "quantifier": "ANY",
        "predicate": {
          "left": {
            "path": "replyTypes",
            "dataType": "array"
          },
          "operator": "contains",
          "right": {
            "value": "message"
          }
        }
      },
      "blocking": false,
      "isActive": true,
      "createdAt": "2026-07-28T08:56:12.000Z",
      "updatedAt": "2026-07-28T08:56:12.000Z"
    }
  ]
  ```
</ResponseExample>
