Create a draft opportunity

POST
/opportunities

Creates the opportunity as a DRAFT. Nothing is charged and no recruitment starts until you call POST /opportunities/{opportunityId}/launch.

The incentive is derived, not sent. There is no field for participant pay, and the amount is fixed when the draft is created. Two paths decide which number you get:

  • Omit feasibility_request_id and the incentive is an automatic estimate made during this call. It is priced from the whole brief, not just its size: the participant count, the task duration, the audience your filters and screening_questions describe, and the recruitment window from expected_days_to_complete. Changing any of those changes the price, so read the result back from pricing on the response; do not quote a price to anyone before you have.
  • Pass a feasibility_request_id and that request's confirmed CPI is honored exactly, with no re-estimate. Submit the brief to POST /feasibility/requests first and poll GET /feasibility/requests/{requestId} until it reads RESPONDED, which is when a price exists. This is the way to control what participants are paid.

The platform fee follows the same split. Priced by feasibility, the confirmed recruitment fee becomes this opportunity's fee, as a flat per-participant amount, so the all-in CPI you agreed is the one you are charged. Priced automatically, it comes from the organization's configuration instead. Either way it is not a per-opportunity input, and neither is the currency (always USD) or the pay cadence (always one_time). pricing on the response carries the all-in cost per participant and the total, and funding says whether the balance covers a launch.

Editing after this call is draft-only: PATCH /opportunities/{opportunityId} returns 409 once the opportunity is launched, and a new recruitment window moves the deadline without re-pricing.

Authorization<token>

API key as Bearer token: Authorization: Bearer

In: header

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" \  -H "Content-Type: application/json" \  -d '{    "title": "How finance teams choose spend software",    "description": "Tell us how your team chose and rolled out its spend management software. Eight written questions, about 30 minutes.",    "project_id": "m4q8x2zc7tn1v0bk5r9wh3jd",    "num_participants": 12,    "business_type": "b2b",    "expected_days_to_complete": 10,    "feasibility_request_id": "tz4a98xxat96iws9zmbrgj3a",    "filters": [      {        "multi_select--country": {          "$in": [            "US",            "CA"          ]        }      },      {        "multi_select--seniority": {          "$in": [            "manager",            "senior-manager",            "director"          ]        }      }    ],    "screening_questions": [      {        "key": "chose_tool",        "text": "Were you involved in choosing your company\'s current spend management software?",        "pick": "one",        "answers": [          {            "text": "Yes, I led or approved the decision",            "qualify_logic": "must"          },          {            "text": "Yes, I gave input",            "qualify_logic": "must"          },          {            "text": "No",            "qualify_logic": "reject"          }        ]      }    ],    "tasks": [      {        "sequence": 1,        "task_type": "interview",        "review_type": "manual_review",        "task_url": "https://research.example.com/studies/spend-software",        "title": "Written interview",        "description": "Answer the eight questions on the interview page, then submit it.",        "duration_minutes": 30      }    ]  }'
{
  "id": "h7k2p9w4c1v6n3x8b5m0q2rt",
  "title": "How finance teams choose spend software",
  "internal_title": null,
  "description": "Tell us how your team chose and rolled out its spend management software. Eight written questions, about 30 minutes.",
  "status": "draft",
  "num_participants": 12,
  "estimated_duration_minutes": 30,
  "filters": [
    {
      "multi_select--country": {
        "$in": [
          "US",
          "CA"
        ]
      }
    },
    {
      "multi_select--seniority": {
        "$in": [
          "manager",
          "senior-manager",
          "director"
        ]
      }
    }
  ],
  "screening_questions": [
    {
      "key": "chose_tool",
      "text": "Were you involved in choosing your company's current spend management software?",
      "pick": "one",
      "answers": [
        {
          "text": "Yes, I led or approved the decision",
          "qualify_logic": "must"
        },
        {
          "text": "Yes, I gave input",
          "qualify_logic": "must"
        },
        {
          "text": "No",
          "qualify_logic": "reject"
        }
      ]
    }
  ],
  "quotas": [],
  "cross_quotas": [],
  "tasks": [
    {
      "sequence": 1,
      "task_type": "interview",
      "review_type": "manual_review",
      "task_url": "https://research.example.com/studies/spend-software",
      "participant_url_template": "https://research.example.com/studies/spend-software?submissionId={submissionId}&teracSubmissionId={submissionId}&taskId={taskId}",
      "title": "Written interview",
      "description": "Answer the eight questions on the interview page, then submit it.",
      "duration_minutes": 30
    }
  ],
  "pricing": {
    "cost_per_participant_cents": 6250,
    "total_cost_cents": 75000,
    "currency": "usd"
  },
  "device_types": [
    "desktop",
    "mobile_ios",
    "mobile_android",
    "other"
  ],
  "business_type": "b2b",
  "candidate_profile": null,
  "required_accounts": [],
  "video_required": "none",
  "screen_share_required": "none",
  "customer_screening_review": "auto_invite",
  "pay_frequency": "one_time",
  "screening_option_randomization": "disabled",
  "forwarding_email_enabled": "disabled",
  "max_responses_per_expert": null,
  "feasibility_request_id": "tz4a98xxat96iws9zmbrgj3a",
  "project_id": "m4q8x2zc7tn1v0bk5r9wh3jd",
  "created_at": "2026-09-28T15:10:05.903Z",
  "funding": {
    "affordable": true,
    "draws_on_credit": false,
    "balance_cents": 240000,
    "shortfall_cents": 0,
    "finance_url": "https://terac.com/acme-research/settings/finance"
  },
  "updated_at": "2026-09-28T15:10:06.412Z",
  "ending_at": "2026-10-08T15:10:05.903Z",
  "launched_at": null,
  "links": {
    "self": "/api/external/v2/opportunities/h7k2p9w4c1v6n3x8b5m0q2rt",
    "launch": "/api/external/v2/opportunities/h7k2p9w4c1v6n3x8b5m0q2rt/launch",
    "submissions": "/api/external/v2/opportunities/h7k2p9w4c1v6n3x8b5m0q2rt/submissions",
    "dashboard": {
      "study": "https://terac.com/acme-research/customer-research-mg4q7x2a/opportunities/h7k2p9w4c1v6n3x8b5m0q2rt",
      "draft_editor": "https://terac.com/acme-research/customer-research-mg4q7x2a/opportunities/create?id=h7k2p9w4c1v6n3x8b5m0q2rt",
      "submissions": null,
      "recruitment": null,
      "task": null,
      "settings": null
    }
  }
}
{
  "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": []
}