Stop opportunity
Permanently ends an opportunity and refunds its unused budget to your organization's balance.
Pending invitations are withdrawn and recruitment cannot be restarted, so pause instead if you
may want to continue. Submissions still awaiting your review block the stop: approve or reject
them first. On an hourly or per-task opportunity, the stop itself approves every expert already
paid on it whose submission is still open. Only an active or paused opportunity can be
stopped; a fulfilled, completed or stopped one returns 409. Delete a draft instead.
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.
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 POST "https://terac.com/api/external/v2/opportunities/string/stop" \ -H "Content-Type: application/json" \ -d '{ "reason": "The audience changed, so a new opportunity replaces this one." }'{
"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": []
}Resume opportunity POST
Resumes a paused opportunity, so it takes new applicants again. Nothing is charged: the budget taken at launch still covers it. Only a `paused` opportunity can be resumed; any other status returns 409.
List submissions for an opportunity GET
Lists an opportunity's submissions, newest first, each with its status and screening answers. Filter to one `status`; the `awaiting_review` ones wait on you to approve or reject them. Applicants still in the screener, or waiting on your invite decision, are not listed; the latter are in `GET /opportunities/{opportunityId}/applicants`. Returns up to `limit` per page; while `pagination.has_more` is true, pass `pagination.next_cursor` back as `cursor` for the next page. For totals, read `submission_stats` on the opportunity rather than counting pages.