Quotas
Steer participant distribution with per-answer and cross-question targets on screening answers.
Quotas let you control how many participants you recruit for specific screening answers. Without quotas, Terac fills participants on a first-come basis. With quotas, recruitment is steered so each target is honored.
Quotas are expressed through cross_quotas — one entry per cell. A cell targets a combination of one or more screening answers:
- One condition — a simple per-answer quota (e.g. "at least 30 senior engineers").
- Two or more conditions — an interlocked cross-tab, so the sample stays balanced on every dimension at once (e.g. "at least 4 who are in Brazil and at an agency").
Cells reference screening questions by their key, and cells that belong to the same cross-tab share a dimension token so they are summed and balanced together.
Quotas require screening questions. The API returns a
BAD_REQUESTerror if you providecross_quotaswithout screening questions.
Fields
| Field | Type | Description |
|---|---|---|
label | string | Human label for the cell, e.g. "Senior engineers" or "Brazil × Agency" (1–200 characters). |
conditions | array | One condition per dimension (1–26). One condition = a simple per-answer quota; two or more interlock a cross-tab across distinct questions. |
conditions[].screening_question | string | The key of a screening question — one dimension of the cell. |
conditions[].answer | string | An answer of that question, by its text. For a grid source use "Row: Column". |
conditions[].operator | string | eq (selected that answer, default) or ne (did not). |
join | string | How the conditions combine: and (default) or or. |
target | integer | Participant count for this cell (positive). |
quota_type | string | How the count is enforced: minimum (default), maximum, or exact. |
dimension | string | Optional. Cells sharing a dimension are summed as one interlocked cross-tab. Use one token per cross-tab. |
quota_type controls how each cell's target is enforced:
quota_type | Meaning |
|---|---|
minimum | At least this many. A floor — recruitment prioritizes the cell while it is short. This is the default. |
maximum | At most this many. A cap — applicants who match are screened out once the cell is full. |
exact | Both a floor and a cap — recruit exactly this many. |
The sum of cell targets does not need to equal num_participants. Recruitment stops when both conditions are true: every minimum/exact cell is met, and num_participants is reached. maximum cells never extend recruitment; they only screen out once full.
Simple quota (one condition)
You want 60 participants, with a floor on senior reviewers and a cap on juniors — one cell per answer, each on the same question.
{
"num_participants": 60,
"screening_questions": [
{
"key": "code_reviews",
"text": "How many code reviews do you perform per week?",
"pick": "one",
"answers": [
{ "text": "5 or more", "qualify_logic": "must_one_of" },
{ "text": "2-4", "qualify_logic": "may" },
{ "text": "0-1", "qualify_logic": "reject" }
]
}
],
"cross_quotas": [
{
"label": "Senior reviewers",
"conditions": [
{ "screening_question": "code_reviews", "answer": "5 or more" }
],
"target": 30,
"quota_type": "minimum"
},
{
"label": "Occasional reviewers",
"conditions": [{ "screening_question": "code_reviews", "answer": "2-4" }],
"target": 20,
"quota_type": "maximum"
}
]
}Recruitment continues until you have at least 30 who answered "5 or more" and 60 total, while never accepting more than 20 who answered "2-4".
Cross-question quota (two or more conditions)
You want 40 participants, balanced across country and organization type. Each cell interlocks two questions; both cells share a dimension so they form one cross-tab.
{
"num_participants": 40,
"screening_questions": [
{
"key": "country",
"text": "Where are you based?",
"pick": "one",
"answers": [
{ "text": "Brazil", "qualify_logic": "may" },
{ "text": "Mexico", "qualify_logic": "may" }
]
},
{
"key": "org_type",
"text": "What kind of organization do you work for?",
"pick": "one",
"answers": [
{ "text": "Agency", "qualify_logic": "may" },
{ "text": "In-house", "qualify_logic": "may" }
]
}
],
"cross_quotas": [
{
"label": "Brazil × Agency",
"dimension": "country_x_org",
"conditions": [
{ "screening_question": "country", "answer": "Brazil" },
{ "screening_question": "org_type", "answer": "Agency" }
],
"target": 4,
"quota_type": "minimum"
},
{
"label": "Brazil × In-house",
"dimension": "country_x_org",
"conditions": [
{ "screening_question": "country", "answer": "Brazil" },
{ "screening_question": "org_type", "answer": "In-house" }
],
"target": 8,
"quota_type": "minimum"
}
]
}Recruitment honors both cells independently: at least 4 participants who are in Brazil and at an agency, and at least 8 who are in Brazil and in-house.