Update opportunity
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.
Authorization
apiKey API key as Bearer token: Authorization: Bearer
In: header
Path Parameters
ID of the opportunity to update
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PATCH "https://terac.com/api/external/v2/opportunities/string" \ -H "Content-Type: application/json" \ -d '{}'{
"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": []
}Get opportunity details GET
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.
Delete a draft opportunity DELETE
Deletes a draft opportunity, which was never charged, and drops it from `GET /opportunities`. A launched opportunity returns 409; end one with `POST /opportunities/{opportunityId}/stop` instead.