Skip to main content

InHire

The InHire integration is stage-driven. When a recruiter moves a candidate (talent) into a stage you configured, Deeper Signals invites them to the assessments of a campaign cloned per job. When they finish, the PDF reports are uploaded to the candidacy, a comment and feedback entry are added and the candidacy is tagged Assessment Completed.

How it works​

  1. Deeper Signals signs in to InHire with a service user you provide, and registers one webhook, Deeper Signals stage trigger, for the JOB_TALENT_STAGE_ADDED event.
  2. You choose a template campaign (a hiring campaign with the assessments, reports and settings) and the stage names that trigger an invitation, optionally restricted to specific jobs.
  3. On a matching stage change, Deeper Signals reads the candidacy and the talent, finds or creates the campaign InHire - <job name> (cloned from the template), finds or creates the candidate by e-mail and sends the invitation.
  4. On completion the reports are written back to the candidacy. The candidate's stage is not changed and no numeric score is written to InHire; recruiters open the Deeper Signals profile link in the comment for details.

Prerequisites​

WhereWhat
InHireYour tenant id, and the e-mail and password of an InHire user allowed to manage webhooks, jobs and talents. The password is used once to sign in and is not stored.
InHireA pipeline stage (per job or shared) that recruiters will use to trigger the assessment, for example Deeper Signals.
Deeper SignalsAn account administrator; API access enabled on the account by Deeper Signals.

The webhook is registered by Deeper Signals; nothing has to be configured manually in InHire.

Setup​

  1. Connect. In the admin app open Settings → Integrations → InHire and enter the tenant, e-mail and password. (API: POST /admin/integrations/inhire/{account}/create with {"tenant", "email", "password"}.)
  2. Configure. Pick the template campaign and the trigger stages. The integration starts in dry run with write-back off, so you can watch events arrive before any candidate is invited. (API: POST /admin/integrations/inhire/{atsIntegration}/configure with {"templateCampaignId": 17, "stages": [{"stageName": "Deeper Signals", "jobId": null}], "dryRun": true, "writeback": false}.)
  3. Test. Run the connection test; it also re-activates the integration after an outage. (API: GET /admin/integrations/inhire/{atsIntegration}/test → {"valid", "active"}.)
  4. Go live. Switch dry run off and write-back on in the same configure call.
  5. Reports. Under Report mapping choose which PDFs are uploaded per assessment.

If the InHire password changes, use Reconnect (POST .../reconnect, same body as create; the tenant must match). Changing the tenant requires a new integration.

The integration view (GET /admin/integrations/inhire/{atsIntegration}) shows the configuration, whether tokens are present, the registered webhook, the last event, the last error and a health block. Secrets are never returned.

Runtime contract​

Inbound: POST /integration/webhook/inhire/{webhookToken}. The random token in the path identifies the integration; the body must be JSON of at most 64 KiB.

FieldRequiredUse
tenantId, jobId, talentId, stageNameyesIdentify the event. Stage names are matched exactly, case-insensitively.
jobName, source, createdAt, stageOriginIdnoKept as event metadata; jobName names the per-job campaign.
Stage event
{
"tenantId": "acme", "jobId": "job-1", "jobName": "Data Analyst",
"previousStageName": "Applied", "stageName": "Deeper Signals", "stageType": "SCREENING",
"talentId": "talent-1", "createdAt": "2026-10-01T12:00:00+00:00"
}

Responses: 200 {"processed": false, "reason": "queued"} once the event is stored for processing; 400 for invalid JSON or missing fields (missing: [...]); 413 for an oversized body; 200 with reason: tenant_mismatch for another tenant. Processing happens asynchronously, so a 200 means accepted, not invited.

Outbound (every call carries X-Tenant and a bearer token; at most 5 requests per second): GET job-talents/{jobId}/talents/{talentId}, signed file upload (POST files/signature, category job-talent-general-files), PATCH job-talents/talents/{jobTalentId} with the new files, a stageChangeComment and a feedback entry reading Deeper Signals assessment completed. Profile: <URL>, and POST job-talents/talents/{id}/tags for Assessment Completed. Webhooks are managed through the InHire webhooks API.

Monitoring​

  • Delivery health runs every 15 minutes and stage health daily: they report configured stages missing in InHire and candidates in a trigger stage who have no Deeper Signals invitation yet. The result is the health block of the integration view (healthy, attention_required, check_failed).
  • Processing reasons you may see on an event: stage_not_configured, duplicate_event, missing_candidate_email, dry_run, integration_inactive.
  • Write-back states: uploading, patching, tagging, succeeded; an ambiguous outcome is flagged for review rather than retried blindly, so a candidate never receives a second invitation e-mail by accident.
  • Expired InHire credentials show as InHire authentication expired; reconnect required.

Limitations​

  • Stage matching is by name (optionally per job); InHire's own webhook filters are only pushed when every configured stage shares the same name or job.
  • The candidate must have an e-mail address on the talent record.
  • Results are written back once all assessments of the campaign are complete; no score or stage change is written to InHire.
  • One InHire integration per Deeper Signals account.