Skip to main content
GET
/
api
/
public
/
v1
/
proposals
/
{proposalId}
curl -sS https://app.opentrain.ai/api/public/v1/proposals/<PROPOSAL_ID> \
  -H "Authorization: Bearer $OT_API_TOKEN"
{
  "proposal": {
    "id": "<PROPOSAL_ID>",
    "jobId": "<JOB_ID>",
    "jobTitle": "Spanish Sentiment Labeling — Social Media Posts",
    "createdAt": "2026-06-11T15:40:00.000Z",
    "updatedAt": "2026-06-12T09:05:00.000Z",
    "status": {
      "raw": "SHORTLISTED",
      "label": "Shortlisted"
    },
    "bid": {
      "amountUsd": 0.06,
      "unit": "PER_LABEL",
      "labelerHourlyRateUsd": null
    },
    "candidate": {
      "id": "<FREELANCER_ID>",
      "profileSlug": "maria-g",
      "displayName": "Maria G.",
      "firstName": "Maria",
      "lastNameInitial": "G",
      "profileTitle": "Text Annotation Specialist",
      "profilePhotoUrl": "https://app.opentrain.ai/<PHOTO_PATH>",
      "countryCode": "ES",
      "country": "Spain",
      "talentType": "FREELANCER",
      "highestEarningsUsd": 2400,
      "reviewCount": 7
    },
    "metrics": {
      "interviewScore": 86,
      "matchScore": 0.91
    },
    "aiInterview": {
      "score": 86,
      "summary": "Strong grasp of sentiment-labeling edge cases; clear communication; native Spanish speaker with prior social-media annotation experience.",
      "transcriptAvailable": true
    },
    "verification": {
      "location": {
        "status": "PASSED",
        "method": "GPS",
        "checkedAt": "2026-06-11T15:38:00.000Z"
      },
      "identity": {
        "verified": true
      }
    },
    "openLabel": null,
    "contract": null
  }
}
Reads a single proposal in full — everything from GET /jobs/{id}/proposals plus the AI-interview block, location/identity verification, labeling-assessment results, and the contract created if you already hired. This is the deep-dive step of the candidate evaluation flow. Candidate identity stays masked pre-hire (first name + last initial). Resume files, personal emails, phone numbers, and payment details are never returned — see privacy. For the full interview transcript, use GET /proposals/{proposalId}/interview. Requirements: proposals:read scope. The proposal must be on a job you own (403 otherwise). Works pre-claim.

Request

proposalId
string
required
The proposal ID, e.g. from the proposals list.

Response

proposal
object

Errors

StatuscodeMeaning
400BAD_REQUESTMissing proposalId
401UNAUTHORIZEDMissing or invalid token
403FORBIDDENMissing proposals:read scope, or the proposal is on another account’s job
404NOT_FOUNDNo such proposal
curl -sS https://app.opentrain.ai/api/public/v1/proposals/<PROPOSAL_ID> \
  -H "Authorization: Bearer $OT_API_TOKEN"
{
  "proposal": {
    "id": "<PROPOSAL_ID>",
    "jobId": "<JOB_ID>",
    "jobTitle": "Spanish Sentiment Labeling — Social Media Posts",
    "createdAt": "2026-06-11T15:40:00.000Z",
    "updatedAt": "2026-06-12T09:05:00.000Z",
    "status": {
      "raw": "SHORTLISTED",
      "label": "Shortlisted"
    },
    "bid": {
      "amountUsd": 0.06,
      "unit": "PER_LABEL",
      "labelerHourlyRateUsd": null
    },
    "candidate": {
      "id": "<FREELANCER_ID>",
      "profileSlug": "maria-g",
      "displayName": "Maria G.",
      "firstName": "Maria",
      "lastNameInitial": "G",
      "profileTitle": "Text Annotation Specialist",
      "profilePhotoUrl": "https://app.opentrain.ai/<PHOTO_PATH>",
      "countryCode": "ES",
      "country": "Spain",
      "talentType": "FREELANCER",
      "highestEarningsUsd": 2400,
      "reviewCount": 7
    },
    "metrics": {
      "interviewScore": 86,
      "matchScore": 0.91
    },
    "aiInterview": {
      "score": 86,
      "summary": "Strong grasp of sentiment-labeling edge cases; clear communication; native Spanish speaker with prior social-media annotation experience.",
      "transcriptAvailable": true
    },
    "verification": {
      "location": {
        "status": "PASSED",
        "method": "GPS",
        "checkedAt": "2026-06-11T15:38:00.000Z"
      },
      "identity": {
        "verified": true
      }
    },
    "openLabel": null,
    "contract": null
  }
}