Implementation Overview
Implementation Type: Minimal Implementation (Webhook-based)Note Format: N/A
Status: Production Ready The Public API integration is not a traditional ATS integration. Instead, it provides a minimal ATS client implementation that supports webhook-based integrations for organizations using Tenzo’s Public API rather than a traditional ATS system.
Configuration
Feature Coverage
Streaming Operations
Streaming Operations
Stream Jobs
Status: Not SupportedMethod:
_stream_jobs(updated_after, statuses)Not supported. Jobs are provided via Public API and stored in AtsJobCache. No streaming needed.Stream Applications
Status: Not SupportedMethod:
_stream_applications(updated_after, for_job_ids)Not supported. Applications are created via Public API calls.Stream Candidates
Status: Not SupportedMethod:
_stream_candidates(updated_after)Not supported. Candidates are provided via Public API.Application Management
Application Management
Move Application to Stage
Status: Not SupportedMethod:
_move_application_to_stage(application, stage)Not applicable - stage management handled externally.Get Disposition Reasons
Status: Not SupportedMethod:
get_disposition_reasons()Not applicable for webhook integration.Reject Application
Status: Not SupportedMethod:
reject_application(application_id, reason_id)Not applicable - application management handled externally.Bulk Reject Applications
Status: Not SupportedMethod:
bulk_reject_applications(application_ids, reason_id)Not applicable.Create Application
Status: Supported (via webhook service)Method:
_create_application_for_candidate(candidate, job)Applications are created when customers submit data via the Public API. The integration stores minimal data and sends results via webhooks.Get All Application Stages
Status: Not SupportedMethod:
_get_all_application_stages()Not applicable.Job Management
Job Management
Get Job by ID
Status: SupportedMethod:
get_job_by_job_id(job_id)Implementation Notes:Retrieves jobs from AtsJobCache that were created via the Public API. Does not query an external ATS.
Get Enhanced Job
Status: Supported (Basic)Method:
get_enhanced_job(kombo_id, remote_job_id)Returns cached job data without additional enhancement. No external ATS to query.Fetch Enhanced Jobs Batch
Status: Not SupportedMethod:
_fetch_enhanced_jobs_batch_from_ats(limit, cursor)Not applicable - jobs come from Public API, not streaming.Candidate Management
Candidate Management
Get Candidate by ID
Status: SupportedMethod:
_get_candidate_by_id(candidate_id)Implementation Notes:Uses temporary candidate storage (
_temp_candidate) for processing. Candidate data is provided via Public API.Find Candidates by Details
Status: Not SupportedMethod:
_find_candidates_by_details(first_name, last_name, email, phone)Not applicable - candidates provided via API, not searched.Get Resume
Status: SupportedMethod:
_get_resume_for_candidate_id(candidate_id)Implementation Notes:Uses temporary resume storage (
_temp_resume) for processing. Resume data provided via Public API.Notes & Attachments
Notes & Attachments
Add Note to Application
Status: Not SupportedMethod:
_add_note_to_application(application, note, note_action_type)Not applicable - no external ATS to write to.Add Note to Candidate
Status: Not SupportedMethod:
_add_note_to_candidate(candidate, note, note_action_type)Not applicable.Add Attachment to Application
Status: Not SupportedMethod:
_add_attachment_to_application(filename, application_id, pdf_b64)Not applicable.Add Attachment to Candidate
Status: Not SupportedMethod:
_add_attachment_to_candidate(filename, candidate_id, pdf_b64)Not applicable.Custom Fields
Custom Fields
All custom field methods raise
NotImplementedError as there is no underlying ATS system to manage custom fields.Implementation Notes
Webhook-Based Architecture
The Public API integration works differently from traditional ATS integrations:- Inbound: Organizations push job and candidate data to Tenzo via Public API
- Processing: Tenzo processes interviews and generates results
- Outbound: Results are sent back via configured webhooks
Temporary Storage
The client uses temporary storage fields:_temp_candidate: Stores candidate data during processing_temp_resume: Stores resume data during processing
Post-Call Results
Override ofpost_call_results() method sends interview results via webhook instead of writing back to an ATS.
Job Cache Usage
Jobs created via Public API are stored inAtsJobCache and retrieved from there rather than from an external system.
Webhook Integration
The Public API client integrates with the webhook service (webhook_service.py) to:
- Send interview results to customer endpoints
- Notify customers of processing completion
- Deliver structured interview data
Known Limitations
Not a Traditional ATS
This integration does not connect to an external ATS system. It’s designed for organizations that want to integrate Tenzo via API/webhooks rather than ATS connectivity.
This integration does not connect to an external ATS system. It’s designed for organizations that want to integrate Tenzo via API/webhooks rather than ATS connectivity.
Minimal Implementation
Many methods raise
Many methods raise
NotImplementedError because they don’t apply to webhook-based integrations. This is expected and intentional.Use Cases
The Public API integration is appropriate for:- Organizations without a traditional ATS
- Custom-built applicant management systems
- Integration with internal HR systems
- Webhook-based workflows
Meeting Copilot Endpoints
The Public API exposes a set of Meeting Copilot resources. The read-only getters —list_meeting_copilot_notes, get_meeting_copilot_note, list_meeting_copilot_templates, and get_meeting_copilot_template — are also surfaced as MCP tools and documented under the Meeting Copilot tag in the Tenzo Public API reference.
Create a Meeting Copilot note
Endpoint:POST /api/v1/meeting-copilot-note
Hand a finished transcript to Tenzo and have it build a Meeting Copilot note, optionally running the same post-meeting pipeline the in-app bot uses when a meeting ends.
Because this is a write operation, it is not exposed as an MCP tool (unlike the read-only Meeting Copilot getters) — call the REST API directly.
The customer-facing contract (request body, transcript limits, response, errors, and a worked example) lives in the Meeting Copilot guide. The generated Tenzo Public API reference covers the same routes under the Meeting Copilot tag. Keep the field tables in the guide only — don’t re-add them here.
Internal notes:
- Access is gated on the
MEETING_NOTES_ACCESSflag viarequire_notes_access; orgs without it get a403on every call regardless of key validity. - Transcript caps are enforced in
CreateMeetingCopilotNoteRequest(5000 lines, 20,000 chars/line, 800,000 total UTF-8 bytes) to keep the note under the Cosmos ~2MB item limit. The byte cap is a Pydanticmodel_validator, so it is not expressible in the generated JSON Schema — the guide states it in prose instead. - If
save_transcriptfails the just-created note is deleted and the caller gets a503, so a retry starts clean. - The optional per-note config fields (
ats_writes— a single flag mapped to both internal togglesupdate_ats_jobandwrite_candidate_fields_to_ats— plusintake_field_overrides,remote_ats_job_id,description_draft,company_remote_id,contact_remote_id) mirror the note’s in-app Config panel. All butintake_field_overridesarecreate_noteparameters; the overrides are applied viasave_note(the same partial-update path the config WebSocket uses) before the transcript is saved and the pipeline scheduled.None/omitted means “inherit the template default”. company_remote_idandcontact_remote_idare intake-only. When provided, the controller queries the org’s ATS client (get_job_creation_entity_ref) to resolve human-readable labels (e.g. BullhornClientCorporationandClientContact) and populatesjob_creation_params.entity_refs, unlocking the ATS Sync entity pickers.- An optional
Idempotency-KeyHTTP header caches successful responses in Redis for 24 hours (public_api:meeting_note:idempotency:{org_id}:{key}), returning identical cached responses on network retries without creating duplicate notes. - A tag only renders in the published ReDoc reference if it appears in both
spec["tags"]andx-tagGroupsinbuild_public_openapi(). Adding a route with a brand-new tag without updating both silently omits it from the docs —find_unrendered_route_tags()catches this in a unit test (routes markedinclude_in_schema=False, like the MCP-only read-only getters, are intentionally excluded).
The public OpenAPI spec is generated at runtime by
build_public_openapi() (server/ats/public_api/public_api.py) and served from the live API — it is deliberately not committed to this repo. Do not add a checked-in copy; it would immediately go stale.Related Files
- Implementation:
server/ats/public_api/public_api_ats_client.py - Webhook Service:
server/ats/public_api/webhook_service.py - Public API Endpoints:
server/ats/public_api/public_api.py - Application Controller:
server/ats/public_api/public_application_controller.py - Job Controller:
server/ats/public_api/public_job_controller.py - Meeting Copilot Note Controller:
server/ats/public_api/public_meeting_note_controller.py - README:
server/ats/public_api/README.md