Ashby · Arazzo Workflow

Ashby Attach a Resume to a Candidate

Version 1.0.0

Mint a presigned upload handle, attach the uploaded resume, and verify the file.

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

Provider

ashby-hq

Workflows

candidate-resume-upload
Create a file upload handle, attach the resume to a candidate, verify it.
Requests a presigned upload handle scoped to CandidateResume, binds the uploaded file to the candidate as their resume, and confirms the attachment by resolving the stored file handle to a url.
3 steps inputs: candidateId, contentLength, contentType, filename outputs: candidateId, resumeFileName, resumeHandle, resumeUrl
1
createUploadHandle
Ask Ashby for a presigned upload target scoped to the CandidateResume context. The response carries the presigned url and form fields for the out-of-band multipart POST, plus the encrypted handle that identifies the file to Ashby once it lands.
2
attachResume
Bind the uploaded file to the candidate as their resume. This step assumes the file has already been POSTed as multipart/form-data to the presigned url from the previous step; that upload goes directly to object storage and is not part of the Ashby JSON API.
3
resolveResumeUrl
Resolve the stored resume handle to a downloadable url, confirming the file is attached and readable. Ashby file urls are short lived, so this call is the correct way to fetch a resume rather than caching a url.

Source API Descriptions

Arazzo Workflow Specification

Raw ↑
arazzo: 1.0.1
info:
  title: Ashby Attach a Resume to a Candidate
  summary: Mint a presigned upload handle, attach the uploaded resume, and verify the file.
  description: >-
    Ashby does not accept resume bytes on its JSON API. Instead the integrator
    asks Ashby for a presigned upload target, POSTs the file to that target out
    of band, and then hands the returned handle back to Ashby to bind the file to
    a candidate. This workflow covers the two API calls that bracket that upload
    plus a read-back that resolves a fresh download url, which is the part
    integrators most often get wrong. 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
- name: fileApi
  url: ../openapi/ashby-hq-file-api-openapi.yml
  type: openapi
workflows:
- workflowId: candidate-resume-upload
  summary: Create a file upload handle, attach the resume to a candidate, verify it.
  description: >-
    Requests a presigned upload handle scoped to CandidateResume, binds the
    uploaded file to the candidate as their resume, and confirms the attachment
    by resolving the stored file handle to a url.
  inputs:
    type: object
    required:
    - candidateId
    - filename
    - contentType
    - contentLength
    properties:
      candidateId:
        type: string
        description: The id of the candidate to attach the resume to.
      filename:
        type: string
        description: The name of the resume file being uploaded, including extension.
      contentType:
        type: string
        description: The MIME type of the resume file (e.g. application/pdf).
      contentLength:
        type: integer
        description: The size of the resume file in bytes.
  steps:
  - stepId: createUploadHandle
    description: >-
      Ask Ashby for a presigned upload target scoped to the CandidateResume
      context. The response carries the presigned url and form fields for the
      out-of-band multipart POST, plus the encrypted handle that identifies the
      file to Ashby once it lands.
    operationId: fileCreateFileUploadHandle
    requestBody:
      contentType: application/json
      payload:
        fileUploadContext: CandidateResume
        filename: $inputs.filename
        contentType: $inputs.contentType
        contentLength: $inputs.contentLength
    successCriteria:
    - condition: $statusCode == 200
    - condition: $response.body#/success == true
    outputs:
      resumeHandle: $response.body#/results/handle
      uploadUrl: $response.body#/results/url
      uploadFields: $response.body#/results/fields
  - stepId: attachResume
    description: >-
      Bind the uploaded file to the candidate as their resume. This step assumes
      the file has already been POSTed as multipart/form-data to the presigned
      url from the previous step; that upload goes directly to object storage and
      is not part of the Ashby JSON API.
    operationId: candidateUploadResume
    requestBody:
      contentType: application/json
      payload:
        candidateId: $inputs.candidateId
        resumeHandle: $steps.createUploadHandle.outputs.resumeHandle
    successCriteria:
    - condition: $statusCode == 200
    - condition: $response.body#/success == true
    outputs:
      candidateId: $response.body#/results/id
      storedResumeHandle: $response.body#/results/resumeFileHandle/handle
      resumeFileName: $response.body#/results/resumeFileHandle/name
  - stepId: resolveResumeUrl
    description: >-
      Resolve the stored resume handle to a downloadable url, confirming the file
      is attached and readable. Ashby file urls are short lived, so this call is
      the correct way to fetch a resume rather than caching a url.
    operationId: fileInfo
    requestBody:
      contentType: application/json
      payload:
        fileHandle: $steps.attachResume.outputs.storedResumeHandle
    successCriteria:
    - condition: $statusCode == 200
    - condition: $response.body#/success == true
    outputs:
      resumeUrl: $response.body#/results/url
  outputs:
    candidateId: $steps.attachResume.outputs.candidateId
    resumeHandle: $steps.attachResume.outputs.storedResumeHandle
    resumeFileName: $steps.attachResume.outputs.resumeFileName
    resumeUrl: $steps.resolveResumeUrl.outputs.resumeUrl

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-resume-upload-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.