openapi: 3.1.0 info: title: HeyMilo Public ATS API description: External developer-facing API for HeyMilo. Create interviewers with agentic workflows, ingest candidates, retrieve interview results, and manage workspace resources. version: 2.0.0 servers: - url: https://api.heymilo.ai description: Production security: - ApiKeyAuth: [] tags: - name: ATS paths: /api/v2/ats/candidates/resolve: post: tags: - ATS summary: Resolve a candidate in the ATS description: Search the connected ATS for a candidate by email or ATS candidate ID. Returns matching candidates so the caller can decide whether to push an existing record or create a new one. Only Bullhorn and Avionte are currently supported. operationId: resolveAtsCandidate parameters: - name: X-API-KEY in: header required: false schema: anyOf: - type: string - type: 'null' title: X-Api-Key - name: Authorization in: header required: false schema: anyOf: - type: string - type: 'null' title: Authorization - name: X-Workspace-Id in: header required: false schema: anyOf: - type: string - type: 'null' title: X-Workspace-Id requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ResolveCandidateRequest' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/SingleResponse_ResolveCandidateResponse_' '400': description: Unsupported ATS provider. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '401': description: Invalid or missing API key. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '429': description: Rate limit exceeded. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /api/v2/ats/candidates/push: post: tags: - ATS summary: Push a candidate to the ATS description: Enqueue a candidate push to the connected ATS. If ``candidate.ats_candidate_id`` is null, a new candidate record is created in the ATS. Returns a queue ``item_id`` that can be polled via the push-status endpoint. Only Bullhorn and Avionte are currently supported. operationId: pushAtsCandidate parameters: - name: X-API-KEY in: header required: false schema: anyOf: - type: string - type: 'null' title: X-Api-Key - name: Authorization in: header required: false schema: anyOf: - type: string - type: 'null' title: Authorization - name: X-Workspace-Id in: header required: false schema: anyOf: - type: string - type: 'null' title: X-Workspace-Id requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PushCandidateRequest' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/SingleResponse_EnqueuePushResponse_' '400': description: Unsupported ATS provider. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '401': description: Invalid or missing API key. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '429': description: Rate limit exceeded. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /api/v2/ats/candidates/push/{item_id}: get: tags: - ATS summary: Get push status description: Poll the status of a queued candidate push by item ID. operationId: getAtsPushStatus parameters: - name: item_id in: path required: true schema: type: string title: Item Id - name: X-API-KEY in: header required: false schema: anyOf: - type: string - type: 'null' title: X-Api-Key - name: Authorization in: header required: false schema: anyOf: - type: string - type: 'null' title: Authorization - name: X-Workspace-Id in: header required: false schema: anyOf: - type: string - type: 'null' title: X-Workspace-Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/SingleResponse_QueueItemStatus_' '400': description: Unsupported ATS provider. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '401': description: Invalid or missing API key. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '429': description: Rate limit exceeded. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /api/v2/ats/connections: get: tags: - ATS summary: List ATS connections description: Return all ATS integrations configured for the authenticated workspace. operationId: listAtsConnections parameters: - name: X-API-KEY in: header required: false schema: anyOf: - type: string - type: 'null' title: X-Api-Key - name: Authorization in: header required: false schema: anyOf: - type: string - type: 'null' title: Authorization - name: X-Workspace-Id in: header required: false schema: anyOf: - type: string - type: 'null' title: X-Workspace-Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ListResponse_AtsConnection_' '400': description: Unsupported ATS provider. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '401': description: Invalid or missing API key. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '429': description: Rate limit exceeded. content: application/json: schema: $ref: '#/components/schemas/APIErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' components: schemas: APIErrorDetail: properties: code: type: string title: Code description: Machine-readable error code examples: - invalid_param message: type: string title: Message description: Human-readable explanation examples: - title must be between 3 and 200 characters param: anyOf: - type: string - type: 'null' title: Param description: Parameter that caused the error examples: - title type: object required: - code - message title: APIErrorDetail SingleResponse_QueueItemStatus_: properties: data: $ref: '#/components/schemas/QueueItemStatus' meta: anyOf: - additionalProperties: true type: object - type: 'null' title: Meta description: Optional metadata. Shape varies by endpoint. type: object required: - data title: SingleResponse[QueueItemStatus] PushCandidateRequest: properties: ats_name: type: string title: Ats Name description: ATS provider name (e.g. 'bullhorn'). posting_id: anyOf: - type: string - type: 'null' title: Posting Id interview_id: anyOf: - type: string - type: 'null' title: Interview Id ingestion_token: anyOf: - type: string - type: 'null' title: Ingestion Token create_submission: type: boolean title: Create Submission description: Also create a candidate-to-job link in the ATS. default: false candidate: $ref: '#/components/schemas/PushCandidatePayload' type: object required: - ats_name - candidate title: PushCandidateRequest SingleResponse_EnqueuePushResponse_: properties: data: $ref: '#/components/schemas/EnqueuePushResponse' meta: anyOf: - additionalProperties: true type: object - type: 'null' title: Meta description: Optional metadata. Shape varies by endpoint. type: object required: - data title: SingleResponse[EnqueuePushResponse] APIError: properties: type: type: string title: Type description: Error category examples: - invalid_request_error code: type: string title: Code description: Machine-readable error code examples: - validation_error message: type: string title: Message description: Human-readable summary examples: - The request body failed validation param: anyOf: - type: string - type: 'null' title: Param description: Top-level parameter that caused the error doc_url: anyOf: - type: string - type: 'null' title: Doc Url description: Link to relevant documentation errors: items: $ref: '#/components/schemas/APIErrorDetail' type: array title: Errors description: Detailed per-field validation errors type: object required: - type - code - message title: APIError ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type type: object required: - loc - msg - type title: ValidationError APIErrorResponse: properties: error: $ref: '#/components/schemas/APIError' type: object required: - error title: APIErrorResponse SingleResponse_ResolveCandidateResponse_: properties: data: $ref: '#/components/schemas/ResolveCandidateResponse' meta: anyOf: - additionalProperties: true type: object - type: 'null' title: Meta description: Optional metadata. Shape varies by endpoint. type: object required: - data title: SingleResponse[ResolveCandidateResponse] ResolveCandidateRequest: properties: ats_name: type: string title: Ats Name description: ATS provider name (e.g. 'bullhorn'). email: anyOf: - type: string - type: 'null' title: Email description: Candidate email to search by. ats_candidate_id: anyOf: - type: string - type: 'null' title: Ats Candidate Id description: ATS-native candidate ID to search by. limit: anyOf: - type: integer - type: 'null' title: Limit description: Max matches to return. type: object required: - ats_name title: ResolveCandidateRequest ResolveCandidateResponse: properties: success: type: boolean title: Success status: type: string title: Status default: '' email: anyOf: - type: string - type: 'null' title: Email ats_candidate_id: anyOf: - type: string - type: 'null' title: Ats Candidate Id matches: items: $ref: '#/components/schemas/CandidateMatch' type: array title: Matches default: [] error: anyOf: - type: string - type: 'null' title: Error type: object required: - success title: ResolveCandidateResponse PushCandidatePayload: properties: ats_candidate_id: anyOf: - type: string - type: 'null' title: Ats Candidate Id description: Existing ATS candidate ID to update. Pass null to create a new candidate. first_name: anyOf: - type: string - type: 'null' title: First Name last_name: anyOf: - type: string - type: 'null' title: Last Name email: anyOf: - type: string - type: 'null' title: Email phone: anyOf: - type: string - type: 'null' title: Phone set_heymilo_source: anyOf: - type: boolean - type: 'null' title: Set Heymilo Source type: object title: PushCandidatePayload QueueItemStatus: properties: item_id: type: string title: Item Id status: type: string title: Status event_type: anyOf: - type: string - type: 'null' title: Event Type retry_count: type: integer title: Retry Count default: 0 failure_instances: items: additionalProperties: true type: object type: array title: Failure Instances default: [] success_details: anyOf: - additionalProperties: true type: object - type: 'null' title: Success Details created_at: anyOf: - type: number - type: 'null' title: Created At updated_at: anyOf: - type: number - type: 'null' title: Updated At type: object required: - item_id - status title: QueueItemStatus CandidateMatch: properties: ats_candidate_id: anyOf: - type: string - type: 'null' title: Ats Candidate Id description: ATS-native candidate ID. first_name: anyOf: - type: string - type: 'null' title: First Name last_name: anyOf: - type: string - type: 'null' title: Last Name email: anyOf: - type: string - type: 'null' title: Email email2: anyOf: - type: string - type: 'null' title: Email2 email3: anyOf: - type: string - type: 'null' title: Email3 phone: anyOf: - type: string - type: 'null' title: Phone status: anyOf: - type: string - type: 'null' title: Status match_reason: anyOf: - type: string - type: 'null' title: Match Reason type: object title: CandidateMatch ListResponse_AtsConnection_: properties: data: items: $ref: '#/components/schemas/AtsConnection' type: array title: Data pagination: $ref: '#/components/schemas/PaginationMeta' type: object required: - data - pagination title: ListResponse[AtsConnection] AtsConnection: properties: integration_id: type: string title: Integration Id description: Unique integration identifier. ats_provider: type: string title: Ats Provider description: ATS provider name. source: type: string title: Source description: 'Integration source: ''native'' or ''kombo''.' default: native display_name: anyOf: - type: string - type: 'null' title: Display Name description: Human-friendly display name for the integration. is_active: type: boolean title: Is Active description: Whether the integration is active. default: true created_at: anyOf: - type: number - type: 'null' title: Created At updated_at: anyOf: - type: number - type: 'null' title: Updated At type: object required: - integration_id - ats_provider title: AtsConnection EnqueuePushResponse: properties: status: type: string title: Status item_id: anyOf: - type: string - type: 'null' title: Item Id description: Queue item ID to poll for status. error: anyOf: - type: string - type: 'null' title: Error type: object required: - status title: EnqueuePushResponse HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError PaginationMeta: properties: has_more: type: boolean title: Has More description: Whether more results exist beyond this page total_count: anyOf: - type: integer - type: 'null' title: Total Count description: Total number of results (if available) url: anyOf: - type: string - type: 'null' title: Url description: URL of this resource type: object required: - has_more title: PaginationMeta securitySchemes: ApiKeyAuth: type: apiKey in: header name: X-API-KEY description: API key for authentication. Pass your key in the X-API-KEY header.