curl --request GET \
--url https://app.dotportion.com/api/v1/submissions/{id}/report \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.dotportion.com/api/v1/submissions/{id}/report', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.dotportion.com/api/v1/submissions/{id}/report"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"data": {
"submission_id": "00000000-0000-4000-8000-000000000031",
"status": "evaluated",
"evaluated": true,
"ship_score": 87,
"verdict": "strong_yes",
"verdict_label": "Strong yes",
"confidence": "low",
"summary": "",
"scored_as_role": null,
"pillars": [
{
"id": "correctness",
"label": "Correctness",
"score": 89,
"low_confidence": false,
"summary": "",
"not_assessed": []
},
{
"id": "craft",
"label": "Craft",
"score": 77,
"low_confidence": false,
"summary": "",
"not_assessed": []
},
{
"id": "ai_fluency",
"label": "AI Fluency",
"score": 75,
"low_confidence": false,
"summary": "",
"not_assessed": []
},
{
"id": "rigor",
"label": "Rigor",
"score": 89,
"low_confidence": false,
"summary": "",
"not_assessed": []
}
],
"strengths": [],
"flags": [],
"interview_questions": [],
"facts": {
"time_used_minutes": null,
"time_allotted_minutes": 60,
"budget_used_dollars": 1.25,
"budget_allotted_dollars": 3,
"ai_authored_pct": null,
"churn_pct": null,
"ai_exchange_count": 0
},
"scope_exclusions": [],
"integrity_status": "flagged",
"pipeline_rank": {
"rank": 2,
"total": 9
},
"tasks": [],
"generated_at": "2026-01-15T12:00:00.000Z"
},
"meta": {
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request",
"details": {
"formErrors": [],
"fieldErrors": {
"name": [
"String must contain at least 1 character(s)"
]
}
},
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "INVALID_TOKEN",
"message": "Invalid or revoked API key",
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "This API key lacks the required scope: write.",
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded for write requests (200/hour). Retry after 2026-01-15T13:00:00.000Z.",
"details": {
"limit": 200,
"remaining": 0,
"reset": 1768482000
},
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "Internal server error",
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}Retrieve a report
The hiring report: a ship score and verdict band, the four scored areas, the evidence behind them, suggested interview questions, and the candidate’s rank in your pipeline.
Before grading finishes the endpoint answers 200 with evaluated: false and null scores rather than 404 — poll it, or watch the submission status.
A pillar’s score is null when there wasn’t enough evidence to report one, and low_confidence marks a score built on thin evidence. Render both as “not enough data”, never as a zero.
not_assessed lists, in plain language, anything the challenge brief gave the candidate no way to demonstrate. Those areas are excluded from scoring entirely rather than scored low.
percentile is omitted until we hold enough comparable attempts for it to mean something. pipeline_rank compares the candidate against your own applicants and is always present once evaluated.
curl --request GET \
--url https://app.dotportion.com/api/v1/submissions/{id}/report \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.dotportion.com/api/v1/submissions/{id}/report', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.dotportion.com/api/v1/submissions/{id}/report"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"data": {
"submission_id": "00000000-0000-4000-8000-000000000031",
"status": "evaluated",
"evaluated": true,
"ship_score": 87,
"verdict": "strong_yes",
"verdict_label": "Strong yes",
"confidence": "low",
"summary": "",
"scored_as_role": null,
"pillars": [
{
"id": "correctness",
"label": "Correctness",
"score": 89,
"low_confidence": false,
"summary": "",
"not_assessed": []
},
{
"id": "craft",
"label": "Craft",
"score": 77,
"low_confidence": false,
"summary": "",
"not_assessed": []
},
{
"id": "ai_fluency",
"label": "AI Fluency",
"score": 75,
"low_confidence": false,
"summary": "",
"not_assessed": []
},
{
"id": "rigor",
"label": "Rigor",
"score": 89,
"low_confidence": false,
"summary": "",
"not_assessed": []
}
],
"strengths": [],
"flags": [],
"interview_questions": [],
"facts": {
"time_used_minutes": null,
"time_allotted_minutes": 60,
"budget_used_dollars": 1.25,
"budget_allotted_dollars": 3,
"ai_authored_pct": null,
"churn_pct": null,
"ai_exchange_count": 0
},
"scope_exclusions": [],
"integrity_status": "flagged",
"pipeline_rank": {
"rank": 2,
"total": 9
},
"tasks": [],
"generated_at": "2026-01-15T12:00:00.000Z"
},
"meta": {
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Invalid request",
"details": {
"formErrors": [],
"fieldErrors": {
"name": [
"String must contain at least 1 character(s)"
]
}
},
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "INVALID_TOKEN",
"message": "Invalid or revoked API key",
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "This API key lacks the required scope: write.",
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded for write requests (200/hour). Retry after 2026-01-15T13:00:00.000Z.",
"details": {
"limit": 200,
"remaining": 0,
"reset": 1768482000
},
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "Internal server error",
"request_id": "req_4f2a9c1e8b7d4a5f9e3c2b1a8d7f6e5c"
}
}Authorizations
Your API key, live (sk_live_…) or test (sk_test_…). Create one in Settings → API keys. Send it as Authorization: Bearer <key> — never in a query string.
Path Parameters
The submission id.
Query Parameters
Response format. pdf is accepted by the schema but not implemented yet.
json, pdf Was this page helpful?