Get opportunity details
Returns one opportunity in full: its brief, audience, screener, tasks and pricing. A draft also carries funding, which says whether the balance covers a launch. A launched one carries submission_stats, quota_progress and screening_stats instead, so poll this to follow recruitment. screening_questions reads back in the shape POST /opportunities accepts, ready to send back on PATCH, and links.dashboard holds its pages in the researcher dashboard.
Authorization
apiKey API key as Bearer token: Authorization: Bearer
In: header
Path Parameters
ID of the opportunity, as returned by POST /opportunities or GET /opportunities.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://terac.com/api/external/v2/opportunities/string"{
"id": "string",
"title": "string",
"internal_title": "string",
"description": "string",
"status": "draft",
"num_participants": 0,
"estimated_duration_minutes": 0,
"filters": [
{
"property1": {
"property1": 0,
"property2": 0
},
"property2": {
"property1": 0,
"property2": 0
}
}
],
"screening_questions": [
{
"key": "string",
"text": "string",
"question_rich_text": "string",
"pick": "one",
"answers": [
{
"text": "string",
"qualify_logic": "may",
"allow_free_text": true
}
],
"grid": {
"pick": "one",
"rows": [
{
"key": "string",
"text": "string"
}
],
"columns": [
{
"value": "string",
"text": "string"
}
],
"cell_actions": [
{
"row": "string",
"column": "string",
"qualify_logic": "may"
}
]
},
"min_qualifying": 1,
"display_condition": {
"conditions": [
{
"screening_question": "string",
"answer": "string",
"operator": "eq"
}
],
"join": "and"
},
"conditional_rules": [
{
"conditions": [
{
"screening_question": "string",
"answer": "string",
"operator": "eq"
}
],
"join": "and",
"outcome": "reject"
}
],
"skip_rules": [
{
"conditions": [
{
"screening_question": "string",
"answer": "string",
"operator": "eq"
}
],
"join": "and",
"target_question": "string"
}
],
"allow_paste": true
}
],
"quotas": [
{
"screening_question": "string",
"targets": [
{
"value": "string",
"count": 1,
"type": "exact"
}
]
}
],
"cross_quotas": [
{
"label": "string",
"conditions": [
{
"screening_question": "string",
"answer": "string",
"operator": "eq"
}
],
"join": "and",
"target": 0,
"quota_type": "exact",
"dimension": "string"
}
],
"tasks": [
{
"sequence": 0,
"task_type": "string",
"review_type": "string",
"task_url": "string",
"participant_url_template": "string",
"title": "string",
"description": "string",
"duration_minutes": 0,
"available_after_sequence": 0,
"available_after_delay_minutes": 0,
"provider": "string",
"calendar_owner": "string",
"event_type_url": "string",
"instructions": "string",
"accepted_mime_types": [
"string"
],
"min_files": 0,
"max_files": 0,
"max_file_size_bytes": 0
}
],
"pricing": {
"cost_per_participant_cents": 0,
"total_cost_cents": 0,
"currency": "usd"
},
"funding": {
"affordable": true,
"draws_on_credit": true,
"balance_cents": 0,
"shortfall_cents": 0,
"finance_url": "string"
},
"device_types": [
"string"
],
"business_type": "string",
"candidate_profile": "string",
"required_accounts": [
"string"
],
"video_required": "string",
"screen_share_required": "string",
"customer_screening_review": "string",
"pay_frequency": "string",
"screening_option_randomization": "string",
"forwarding_email_enabled": "string",
"max_responses_per_expert": 0,
"feasibility_request_id": "string",
"project_id": "string",
"created_at": "string",
"updated_at": "string",
"ending_at": "string",
"launched_at": "string",
"links": {
"self": "string",
"launch": "string",
"submissions": "string",
"dashboard": {
"study": "string",
"draft_editor": "string",
"submissions": "string",
"recruitment": "string",
"task": "string",
"settings": "string"
}
},
"submission_stats": {
"total": 0,
"in_progress": 0,
"awaiting_review": 0,
"approved": 0,
"rejected": 0
},
"quota_progress": [
{
"screening_question": "string",
"targets": [
{
"value": "string",
"count": 0,
"current": 0,
"type": "string"
}
]
}
],
"cross_quota_progress": [
{
"label": "string",
"conditions": [
{
"screening_question": "string",
"answer": "string",
"operator": "eq"
}
],
"join": "and",
"target": 0,
"quota_type": "exact",
"dimension": "string",
"current": 0
}
],
"screening_stats": [
{
"screening_question": "string",
"graded": 0,
"rejected": 0,
"rejection_rate": 0,
"answers": [
{
"text": "string",
"selected": 0,
"share": 0
}
]
}
]
}{
"code": "BAD_REQUEST",
"message": "Invalid input data",
"issues": []
}{
"error": {
"code": "UNAUTHORIZED",
"message": "API key required. Include Authorization: Bearer <key> header."
}
}{
"error": {
"code": "FORBIDDEN",
"message": "This account is not permitted to use the API."
}
}{
"code": "NOT_FOUND",
"message": "Not found",
"issues": []
}{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Retry after 61 seconds."
}
}{
"code": "INTERNAL_SERVER_ERROR",
"message": "Internal server error",
"issues": []
}List opportunities GET
Lists your organization's opportunities, newest first, with each one's status, target and pricing. Filter by `projectId` or by one `status`. Returns up to `limit` per page; while `pagination.has_more` is true, pass `pagination.next_cursor` back as `cursor` for the next page. Deleted opportunities are left out. `pricing` is what launching charged, so it is null on a draft; read a draft's estimate from `GET /opportunities/{opportunityId}`.
Update opportunity PATCH
Edits a draft opportunity; send only the fields you are changing. A list you send (`tasks`, `filters`, `screening_questions`, `quotas`, `cross_quotas`) replaces the stored one rather than merging into it, so read the opportunity first and send the whole list back. `quotas` and `cross_quotas` are only accepted alongside `screening_questions`. A new `expected_days_to_complete` moves the deadline without re-pricing. A request that changes nothing returns 400, and a launched opportunity returns 409.