Ashby · Arazzo Workflow

Ashby Candidate Intake with Deduplication

Version 1.0.0

Search for a candidate by email, then update the match or create a new candidate.

1 workflow 1 source API 1 provider
View Spec View on GitHub ATSRecruitingTalent AcquisitionSourcingCRMSchedulingAnalyticsHiringHR TechArtificial IntelligenceArazzoWorkflows

Provider

ashby-hq

Workflows

candidate-intake
Deduplicate on email, create or update the candidate, then note and verify.
Searches Ashby for an existing candidate with the supplied email, updates the match or creates a new candidate, records an intake note, and fetches the final candidate profile.
5 steps inputs: email, githubUrl, linkedInUrl, name, note, phoneNumber outputs: candidateId, candidateName, noteId, primaryEmail
1
findCandidate
Search Ashby for an existing candidate with this email. Ashby matches on the candidate's email addresses, so this is the reliable dedupe key before any write.
2
updateExisting
Update the matched candidate with the supplied contact details. Only the supplied fields are changed; everything else on the profile is left intact.
3
createCandidate
Create a new candidate when the email search returned no match.
4
recordIntakeNote
Attach an intake note to the candidate so recruiters can see where the record came from. Runs against whichever candidate id the branch produced.
5
readCandidate
Read the candidate back to confirm the write landed and to hand the caller a complete profile.

Source API Descriptions

Arazzo Workflow Specification

Raw ↑
arazzo: 1.0.1
info:
  title: Ashby Candidate Intake with Deduplication
  summary: Search for a candidate by email, then update the match or create a new candidate.
  description: >-
    The foundational Ashby integration pattern for any system that pushes people
    into the ATS. Sourcing tools, referral portals, and CRM syncs all need to
    avoid creating duplicate candidate records, so this workflow searches by
    email first and then branches: when a candidate already exists it updates the
    existing record, and when none is found it creates one. Either way the flow
    attaches an intake note and reads the candidate back so the caller ends with
    a confirmed profile. Every step spells out its request inline so the flow can
    be read and executed without opening the underlying OpenAPI description.
  version: 1.0.0
  x-realizes-capability-ids:
  - BC-300.10
  x-capability-derivation:
    method: 'deterministic join: sourceDescriptions -> per-tag OpenAPI -> tag/capability edge. No classification at this step.'
    min_confidence: 0.7
    sources:
    - capability_id: BC-300.10
      capability_name: Talent Acquisition Management
      spec: ashby-hq-candidate-api-openapi.yml
      confidence: 0.95
    model: Turbo EA Capabilities by Vincent Verdet — Turbo EA, https://github.com/vincentmakes/turbo-ea-capabilities, CC BY 4.0
sourceDescriptions:
- name: candidateApi
  url: ../openapi/ashby-hq-candidate-api-openapi.yml
  type: openapi
workflows:
- workflowId: candidate-intake
  summary: Deduplicate on email, create or update the candidate, then note and verify.
  description: >-
    Searches Ashby for an existing candidate with the supplied email, updates the
    match or creates a new candidate, records an intake note, and fetches the
    final candidate profile.
  inputs:
    type: object
    required:
    - email
    - name
    properties:
      email:
        type: string
        description: Primary personal email of the candidate, used as the dedupe key.
      name:
        type: string
        description: The first and last name of the candidate (e.g. "Adam Hart").
      phoneNumber:
        type: string
        description: Primary personal phone number of the candidate.
      linkedInUrl:
        type: string
        description: Url to the candidate's LinkedIn profile. Must be a valid Url.
      githubUrl:
        type: string
        description: Url to the candidate's GitHub profile. Must be a valid Url.
      note:
        type: string
        description: Intake note to record on the candidate (e.g. where they came from).
  steps:
  - stepId: findCandidate
    description: >-
      Search Ashby for an existing candidate with this email. Ashby matches on the
      candidate's email addresses, so this is the reliable dedupe key before any
      write.
    operationId: candidateSearch
    requestBody:
      contentType: application/json
      payload:
        email: $inputs.email
    successCriteria:
    - condition: $statusCode == 200
    - condition: $response.body#/success == true
    outputs:
      matchedCandidateId: $response.body#/results/0/id
    onSuccess:
    - name: candidateExists
      type: goto
      stepId: updateExisting
      criteria:
      - context: $response.body
        condition: $.results.length > 0
        type: jsonpath
    - name: candidateMissing
      type: goto
      stepId: createCandidate
      criteria:
      - context: $response.body
        condition: $.results.length == 0
        type: jsonpath
  - stepId: updateExisting
    description: >-
      Update the matched candidate with the supplied contact details. Only the
      supplied fields are changed; everything else on the profile is left intact.
    operationId: candidateUpdate
    requestBody:
      contentType: application/json
      payload:
        candidateId: $steps.findCandidate.outputs.matchedCandidateId
        name: $inputs.name
        phoneNumber: $inputs.phoneNumber
        linkedInUrl: $inputs.linkedInUrl
        githubUrl: $inputs.githubUrl
    successCriteria:
    - condition: $statusCode == 200
    - condition: $response.body#/success == true
    outputs:
      candidateId: $response.body#/results/id
    onSuccess:
    - name: continueToNote
      type: goto
      stepId: recordIntakeNote
  - stepId: createCandidate
    description: >-
      Create a new candidate when the email search returned no match.
    operationId: candidateCreate
    requestBody:
      contentType: application/json
      payload:
        name: $inputs.name
        email: $inputs.email
        phoneNumber: $inputs.phoneNumber
        linkedInUrl: $inputs.linkedInUrl
        githubUrl: $inputs.githubUrl
    successCriteria:
    - condition: $statusCode == 200
    - condition: $response.body#/success == true
    outputs:
      candidateId: $response.body#/results/id
  - stepId: recordIntakeNote
    description: >-
      Attach an intake note to the candidate so recruiters can see where the
      record came from. Runs against whichever candidate id the branch produced.
    operationId: candidateCreateNote
    requestBody:
      contentType: application/json
      payload:
        candidateId: $steps.createCandidate.outputs.candidateId
        note: $inputs.note
        sendNotifications: false
    successCriteria:
    - condition: $statusCode == 200
    - condition: $response.body#/success == true
    outputs:
      noteId: $response.body#/results/id
  - stepId: readCandidate
    description: >-
      Read the candidate back to confirm the write landed and to hand the caller
      a complete profile.
    operationId: candidateInfo
    requestBody:
      contentType: application/json
      payload:
        id: $steps.createCandidate.outputs.candidateId
    successCriteria:
    - condition: $statusCode == 200
    - condition: $response.body#/success == true
    outputs:
      candidateId: $response.body#/results/id
      candidateName: $response.body#/results/name
      primaryEmail: $response.body#/results/primaryEmailAddress/value
  outputs:
    candidateId: $steps.readCandidate.outputs.candidateId
    candidateName: $steps.readCandidate.outputs.candidateName
    primaryEmail: $steps.readCandidate.outputs.primaryEmail
    noteId: $steps.recordIntakeNote.outputs.noteId

Work with this as data

Every workflow here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for arazzo workflows

4 MCP tools reach this
  • find_arazzoBrowse and filter every workflow in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This workflow
curl "https://apis.io/api/v1/arazzo/ashby-hq-candidate-intake-workflow"
All arazzo workflows
curl "https://apis.io/api/v1/arazzo?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.