{"openapi":"3.1.0","info":{"title":"Assessly API","version":"1.0.0","summary":"Read assessments and candidate submissions from Assessly.","description":"Assessly is an AI candidate screening platform. Companies build a short practical assessment for a role, send a link to candidates, and Assessly scores each answer and explains the reasoning.\n\nThis API reads that data back out: the assessments a company has built, and the submissions candidates have made to them, including per-question scores and the AI summary.\n\n## Authentication\n\nEvery request needs an API key in the `Authorization` header, as `Bearer sk_live_<random_string>`. Keys are created in the dashboard under Settings then Integrations, and each key carries a set of scopes. API access is not available on the Free plan.\n\n## Scopes\n\n- `submissions.read`: Read submission data (default)\n- `submissions.write`: Create and update submissions\n- `assessments.read`: Read assessment data and configurations\n- `assessments.write`: Create, update, and delete assessments\n- `webhooks.read`: View webhook configurations\n- `webhooks.write`: Create and manage webhooks\n\n## Rate limits\n\nRequests per hour, by plan:\n\n- Starter: 500\n- Pro: 2,000\n- Business: 5,000\n- Enterprise: Custom\n\nThe ceiling for the current plan comes back on every success as `X-RateLimit-Limit`. A request over the limit returns 429 with `Retry-After`.\n\n## Webhooks\n\nRather than polling this API for new submissions, subscribe to a webhook. Assessly signs each delivery with HMAC SHA-256 and sends these events:\n\n- `submission.created`: Triggered when a new submission is created\n- `submission.updated`: Triggered when a submission is updated\n- `submission.completed`: Triggered when a submission is completed\n- `submission.scored`: Triggered when AI scoring is finished\n\nWebhook setup and signature verification are documented at https://assessly.app/docs/api.\n\n## Personal data\n\nSubmission responses contain candidate personal data: name, email, phone and anything the candidate wrote. Handle it under the same terms the company accepted, and delete it through the candidate privacy flow rather than by dropping your own copy.","contact":{"name":"Assessly support","email":"support@assessly.app","url":"https://assessly.app/contact"},"termsOfService":"https://assessly.app/terms","license":{"name":"Proprietary","url":"https://assessly.app/terms"}},"externalDocs":{"description":"API reference, code samples in five languages, and webhook setup","url":"https://assessly.app/docs/api"},"servers":[{"url":"https://assessly.app","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Assessments","description":"The assessments a company has built: questions, settings and status."},{"name":"Submissions","description":"What candidates answered, with per-question scores and the AI summary. Contains personal data."}],"paths":{"/api/v1/submissions":{"get":{"operationId":"listSubmissions","summary":"List all submissions for your company with optional filtering and pagination","description":"List all submissions for your company with optional filtering and pagination. Requires the `submissions.read` scope. Results are paginated. Read `pagination.has_more` or compare `page` against `pagination.total_pages` before requesting the next page.","tags":["Submissions"],"x-required-scopes":["submissions.read"],"parameters":[{"name":"assessment_id","in":"query","required":false,"description":"Only submissions to this assessment","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"completed or pending","schema":{"type":"string"}},{"name":"candidate_name","in":"query","required":false,"description":"Partial match on the candidate name","schema":{"type":"string"}},{"name":"candidate_email","in":"query","required":false,"description":"Partial match on the candidate email","schema":{"type":"string"}},{"name":"min_score","in":"query","required":false,"description":"Score at or above this value","schema":{"type":"number"}},{"name":"max_score","in":"query","required":false,"description":"Score at or below this value","schema":{"type":"number"}},{"name":"submitted_after","in":"query","required":false,"description":"Submitted after this date (ISO 8601)","schema":{"type":"string"}},{"name":"submitted_before","in":"query","required":false,"description":"Submitted before this date (ISO 8601)","schema":{"type":"string"}},{"name":"has_ai_summary","in":"query","required":false,"description":"Whether an AI summary exists","schema":{"type":"boolean"}},{"name":"sort_by","in":"query","required":false,"description":"submitted_at, score, time_spent_seconds or status","schema":{"type":"string"}},{"name":"sort_order","in":"query","required":false,"description":"asc or desc. Default: desc","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number. Default: 1","schema":{"type":"number"}},{"name":"limit","in":"query","required":false,"description":"Items per page. Default: 50, maximum: 100","schema":{"type":"number"}}],"responses":{"200":{"description":"A page of submissions.","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per hour on the current plan.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"assessment_id":{"type":"string"},"candidate_name":{"type":"string"},"candidate_email":{"type":"string"},"status":{"type":"string"},"score":{"type":"integer"},"submitted_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"custom_fields":{"type":"object","properties":{"source":{"type":"string"},"campaign_id":{"type":"string"},"referrer":{"type":"string"}}}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"total_pages":{"type":"integer"}}}}},"example":{"data":[{"id":"sub_123","assessment_id":"abc123","candidate_name":"John Doe","candidate_email":"john@example.com","status":"completed","score":85,"submitted_at":"2024-11-24T10:30:00Z","created_at":"2024-11-24T10:00:00Z","custom_fields":{"source":"linkedin","campaign_id":"summer2024","referrer":"john_doe"}}],"pagination":{"page":1,"limit":50,"total":150,"total_pages":3}}}}},"400":{"description":"A parameter was malformed. `code` is `INVALID_PARAMETER`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key was missing or is not valid. `code` is `MISSING_API_KEY`, `INVALID_API_KEY` or `AUTH_ERROR`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the required scope, or the company is on a plan without API access. `code` is `INSUFFICIENT_PERMISSIONS` or `PLAN_UPGRADE_REQUIRED`. API access is not available on the Free plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The hourly rate limit for the plan was exceeded. `code` is `RATE_LIMIT_EXCEEDED`. Wait for the number of seconds in `Retry-After` before retrying.","headers":{"Retry-After":{"description":"Seconds to wait before the next request.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, as an ISO 8601 timestamp.","schema":{"type":"string","format":"date-time"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed on our side. `code` is `DATABASE_ERROR` or `UNKNOWN_ERROR`. The request can be retried.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/submissions/{id}":{"get":{"operationId":"getSubmission","summary":"Retrieve detailed information about a specific submission, including all responses and AI analysis","description":"Retrieve detailed information about a specific submission, including all responses and AI analysis. Requires the `submissions.read` scope.","tags":["Submissions"],"x-required-scopes":["submissions.read"],"parameters":[{"name":"id","in":"path","required":true,"description":"The submission id","schema":{"type":"string"}}],"responses":{"200":{"description":"The submission.","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per hour on the current plan.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"assessment_id":{"type":"string"},"assessment_title":{"type":"string"},"candidate_info":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"}}},"responses":{"type":"array","items":{"type":"object","properties":{"question_id":{"type":"string"},"question_text":{"type":"string"},"question_type":{"type":"string"},"answer":{"type":"string"},"score":{"type":"integer"},"ai_feedback":{"type":"string"}}}},"submitted_at":{"type":"string","format":"date-time"},"status":{"type":"string"},"score":{"type":"integer"},"grade":{"type":"string"},"ai_summary":{"type":"object","properties":{"overall":{"type":"string"},"strengths":{"type":"array","items":{"type":"string"}},"concerns":{"type":"array","items":{}}}},"time_spent_seconds":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"custom_fields":{"type":"object","properties":{"source":{"type":"string"},"campaign_id":{"type":"string"},"referrer":{"type":"string"},"ats_candidate_id":{"type":"string"}}}}},"example":{"id":"sub_123","assessment_id":"abc123","assessment_title":"Frontend Developer Assessment","candidate_info":{"name":"John Doe","email":"john@example.com","phone":"+1234567890"},"responses":[{"question_id":"q_001","question_text":"Describe your experience with React","question_type":"text","answer":"I have 3 years of experience...","score":90,"ai_feedback":"Excellent answer demonstrating deep understanding."}],"submitted_at":"2024-11-24T10:30:00Z","status":"completed","score":85,"grade":"A","ai_summary":{"overall":"Strong candidate with excellent technical skills...","strengths":["Problem solving","Communication","Technical knowledge"],"concerns":[]},"time_spent_seconds":1800,"created_at":"2024-11-24T10:00:00Z","custom_fields":{"source":"linkedin","campaign_id":"summer2024","referrer":"john_doe","ats_candidate_id":"12345"}}}}},"400":{"description":"A parameter was malformed. `code` is `INVALID_PARAMETER`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key was missing or is not valid. `code` is `MISSING_API_KEY`, `INVALID_API_KEY` or `AUTH_ERROR`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the required scope, or the company is on a plan without API access. `code` is `INSUFFICIENT_PERMISSIONS` or `PLAN_UPGRADE_REQUIRED`. API access is not available on the Free plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No submission with that id belongs to the company the key authenticates. `code` is `SUBMISSION_NOT_FOUND`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The hourly rate limit for the plan was exceeded. `code` is `RATE_LIMIT_EXCEEDED`. Wait for the number of seconds in `Retry-After` before retrying.","headers":{"Retry-After":{"description":"Seconds to wait before the next request.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, as an ISO 8601 timestamp.","schema":{"type":"string","format":"date-time"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed on our side. `code` is `DATABASE_ERROR` or `UNKNOWN_ERROR`. The request can be retried.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/assessments":{"get":{"operationId":"listAssessments","summary":"List all assessments for your company with optional filtering and pagination","description":"List all assessments for your company with optional filtering and pagination. Requires the `assessments.read` scope. Results are paginated. Read `pagination.has_more` or compare `page` against `pagination.total_pages` before requesting the next page.","tags":["Assessments"],"x-required-scopes":["assessments.read"],"parameters":[{"name":"status","in":"query","required":false,"description":"active, paused or archived","schema":{"type":"string"}},{"name":"search","in":"query","required":false,"description":"Matches the title and the description","schema":{"type":"string"}},{"name":"is_public","in":"query","required":false,"description":"Whether the assessment is public","schema":{"type":"boolean"}},{"name":"created_after","in":"query","required":false,"description":"Created after this date (ISO 8601)","schema":{"type":"string"}},{"name":"created_before","in":"query","required":false,"description":"Created before this date (ISO 8601)","schema":{"type":"string"}},{"name":"has_time_limit","in":"query","required":false,"description":"Whether a time limit is set","schema":{"type":"boolean"}},{"name":"has_max_submissions","in":"query","required":false,"description":"Whether a submission cap is set","schema":{"type":"boolean"}},{"name":"has_expiry_date","in":"query","required":false,"description":"Whether an expiry date is set","schema":{"type":"boolean"}},{"name":"include_counts","in":"query","required":false,"description":"Add submission counts to each row","schema":{"type":"boolean"}},{"name":"sort_by","in":"query","required":false,"description":"created_at, updated_at, title or status","schema":{"type":"string"}},{"name":"sort_order","in":"query","required":false,"description":"asc or desc. Default: desc","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number. Default: 1","schema":{"type":"number"}},{"name":"limit","in":"query","required":false,"description":"Items per page. Default: 50, maximum: 100","schema":{"type":"number"}}],"responses":{"200":{"description":"A page of assessments.","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per hour on the current plan.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string"},"status":{"type":"string"},"is_public":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"]},"time_limit_minutes":{"type":"integer"},"max_submissions":{"type":"integer"},"max_attempts":{"type":"integer"},"show_timer":{"type":"boolean"},"assessment_format":{"type":"string"},"submission_count":{"type":"integer"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"total_pages":{"type":"integer"}}}}},"example":{"data":[{"id":"abc123","title":"Frontend Developer Assessment","slug":"frontend-developer-assessment","description":"Assess frontend development skills","status":"active","is_public":true,"created_at":"2024-11-01T10:00:00Z","updated_at":"2024-11-24T10:00:00Z","expires_at":null,"time_limit_minutes":60,"max_submissions":100,"max_attempts":2,"show_timer":true,"assessment_format":"standard","submission_count":45}],"pagination":{"page":1,"limit":50,"total":12,"total_pages":1}}}}},"400":{"description":"A parameter was malformed. `code` is `INVALID_PARAMETER`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key was missing or is not valid. `code` is `MISSING_API_KEY`, `INVALID_API_KEY` or `AUTH_ERROR`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the required scope, or the company is on a plan without API access. `code` is `INSUFFICIENT_PERMISSIONS` or `PLAN_UPGRADE_REQUIRED`. API access is not available on the Free plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The hourly rate limit for the plan was exceeded. `code` is `RATE_LIMIT_EXCEEDED`. Wait for the number of seconds in `Retry-After` before retrying.","headers":{"Retry-After":{"description":"Seconds to wait before the next request.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, as an ISO 8601 timestamp.","schema":{"type":"string","format":"date-time"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed on our side. `code` is `DATABASE_ERROR` or `UNKNOWN_ERROR`. The request can be retried.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/assessments/{id}":{"get":{"operationId":"getAssessment","summary":"Retrieve detailed information about a specific assessment, including all questions and configuration","description":"Retrieve detailed information about a specific assessment, including all questions and configuration. Requires the `assessments.read` scope.","tags":["Assessments"],"x-required-scopes":["assessments.read"],"parameters":[{"name":"id","in":"path","required":true,"description":"The assessment id","schema":{"type":"string"}}],"responses":{"200":{"description":"The assessment.","headers":{"X-RateLimit-Limit":{"description":"Requests allowed per hour on the current plan.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"instructions":{"type":"string"},"status":{"type":"string"},"password_protected":{"type":"boolean"},"time_limit_minutes":{"type":"integer"},"personal_info_fields":{"type":"array","items":{"type":"string"}},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"question":{"type":"string"},"description":{"type":"string"},"required":{"type":"boolean"},"order":{"type":"integer"},"validation_rules":{"type":"object","properties":{"min_length":{"type":"integer"},"max_length":{"type":"integer"}}}}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"total_submissions":{"type":"integer"}}},"example":{"id":"abc123","title":"Frontend Developer Assessment","description":"Assess frontend development skills including React, TypeScript, and CSS","instructions":"Complete all questions within 60 minutes","status":"active","password_protected":false,"time_limit_minutes":60,"personal_info_fields":["name","email","phone"],"questions":[{"id":"q_001","type":"text","question":"Describe your experience with React","description":"Please provide details about your React experience","required":true,"order":1,"validation_rules":{"min_length":50,"max_length":1000}},{"id":"q_002","type":"multiple_choice","question":"Which React hooks have you used?","options":["useState","useEffect","useContext","useReducer"],"required":true,"order":2}],"created_at":"2024-11-01T10:00:00Z","updated_at":"2024-11-24T10:00:00Z","total_submissions":45}}}},"400":{"description":"A parameter was malformed. `code` is `INVALID_PARAMETER`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key was missing or is not valid. `code` is `MISSING_API_KEY`, `INVALID_API_KEY` or `AUTH_ERROR`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the required scope, or the company is on a plan without API access. `code` is `INSUFFICIENT_PERMISSIONS` or `PLAN_UPGRADE_REQUIRED`. API access is not available on the Free plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No assessment with that id belongs to the company the key authenticates. `code` is `ASSESSMENT_NOT_FOUND`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The hourly rate limit for the plan was exceeded. `code` is `RATE_LIMIT_EXCEEDED`. Wait for the number of seconds in `Retry-After` before retrying.","headers":{"Retry-After":{"description":"Seconds to wait before the next request.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the current window resets, as an ISO 8601 timestamp.","schema":{"type":"string","format":"date-time"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed on our side. `code` is `DATABASE_ERROR` or `UNKNOWN_ERROR`. The request can be retried.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"sk_live_<random_string>","description":"A scoped API key, created in the dashboard under Settings then Integrations. Send it as `Authorization: Bearer sk_live_...`. The bare key without the `Bearer ` prefix is also accepted."}},"schemas":{"Error":{"type":"object","description":"Every failure returns this shape as JSON. Branch on `code`, which is stable; `message` is written for people and may be reworded.","required":["error","code","message"],"properties":{"error":{"type":"string","description":"The HTTP status name, for example `Bad Request`."},"code":{"type":"string","description":"A stable machine-readable code.","enum":["MISSING_API_KEY","INVALID_API_KEY","PLAN_UPGRADE_REQUIRED","AUTH_ERROR","INSUFFICIENT_PERMISSIONS","RATE_LIMIT_EXCEEDED","INVALID_PARAMETER","ASSESSMENT_NOT_FOUND","SUBMISSION_NOT_FOUND","DATABASE_ERROR","UNKNOWN_ERROR"]},"message":{"type":"string","description":"What went wrong and, where there is one, how to fix it."}},"examples":[{"error":"Unauthorized","code":"MISSING_API_KEY","message":"API key is required. Include it in the Authorization header as \"Bearer sk_live_...\""}]}}}}