Ashby Files API

Look up file metadata and request presigned upload URLs for candidate resumes, application attachments, and partner-provided assessment artifacts. Two-step pattern — request presigned URL, then PUT bytes — keeps payloads off Ashby's API surface.

Ashby Files API is one of 15 APIs that Ashby publishes on the APIs.io network, described by a machine-readable OpenAPI specification.

This API exposes 1 machine-runnable capability that can be deployed as REST, MCP, or Agent Skill surfaces via Naftiko.

Tagged areas include Files, Uploads, and Recruiting. The published artifact set on APIs.io includes API documentation, an OpenAPI specification, and 1 Naftiko capability spec.

OpenAPI Specification

ashby-openapi.yml Raw ↑
openapi: 3.1.0
info:
  version: 1.0.0
  title: Ashby API
  description: Complete public API for accessing resources in your Ashby instance. Includes applications, candidates, jobs, interviews, offers, surveys, custom fields, organization metadata, files, reports, approvals, and webhooks.
  contact:
    name: Ashby Support
    url: https://app.ashbyhq.com/support
    email: [email protected]
servers:
- url: https://api.ashbyhq.com
security:
- BasicAuth: []
components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
      description: HTTP Basic Auth. Send your Ashby API key as the username and leave the password blank.
    WebhookSignature:
      type: apiKey
      in: header
      name: Ashby-Signature
      description: HMAC-SHA256 signature of the webhook payload, used to verify webhook authenticity.
paths:
  /apiKey.info:
    post:
      summary: apiKey.info
      description: 'Retrieve information about the API key being used to make the request.


        **Requires the [`apiKeysRead`](authentication#permissions-apikeyinfo) permission.**

        '
      operationId: apiKeyInfo
      tags:
      - API Key
      requestBody:
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: Responses for the apiKey.info endpoint
          content:
            application/json:
              schema:
                oneOf:
                - title: Success response
                  allOf:
                  - $ref: '#/paths/~1job.info/post/responses/200/content/application~1json/schema/oneOf/0/allOf/0'
                  - type: object
                    properties:
                      results:
                        type: object
                        properties:
                          title:
                            type: string
                            description: The name of the API key.
                            example: Custom Job Board API key
                          createdAt:
                            $ref: '#/paths/~1candidate.createNote/post/requestBody/content/application~1json/schema/properties/createdAt'
                          scopes:
                            type: array
                            description: List of permission scopes that this API key is authorized for.
                            items:
                              type: string
                            example:
                            - jobs:read
                            - candidates:read
                    required:
                    - results
                - title: Error response
                  $ref: '#/paths/~1report.generate/post/responses/429/content/application~1json/schema'
      security:
      - BasicAuth: []
  /application.addHiringTeamMember:
    post:
      summary: application.addHiringTeamMember
      description: "Adds an Ashby user to the hiring team at the application level. \n\n**Requires the [`candidateWrite`](authentication#permissions-applicationaddhiringteammember) permission.**\n"
      operationId: applicationaddhiringteammember
      tags:
      - Application
      requestBody:
        content:
          application/json:
            schema:
              required:
              - applicationId
              - teamMemberId
              - roleId
              properties:
                applicationId:
                  allOf:
                  - description: The application to assign the user a role on.
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                teamMemberId:
                  allOf:
                  - description: The id of the user to assign the role to.
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                roleId:
                  allOf:
                  - description: The id of the hiring team role to assign.
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
      responses:
        '200':
          description: Responses for the application.addHiringTeamMember endpoint
          content:
            application/json:
              schema:
                oneOf:
                - title: Success response
                  allOf:
                  - $ref: '#/paths/~1job.info/post/responses/200/content/application~1json/schema/oneOf/0/allOf/0'
                  - type: object
                    properties:
                      results:
                        $ref: '#/paths/~1hiringTeam.addMember/post/responses/200/content/application~1json/schema/oneOf/0/allOf/1/properties/results'
                    required:
                    - results
                - title: Error response
                  $ref: '#/paths/~1report.generate/post/responses/429/content/application~1json/schema'
  /application.changeSource:
    post:
      summary: application.changeSource
      operationId: applicationChangeSource
      description: 'Change the source of an application.


        **Requires the [`candidatesWrite`](authentication#permissions-applicationchangesource) permission.**

        '
      tags:
      - Application
      requestBody:
        content:
          application/json:
            schema:
              properties:
                applicationId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The id of the application to update the source of
                sourceId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The source to set on the application. Pass null to unset an application's source.
              required:
              - applicationId
              - sourceId
              example:
                applicationId: 3ae2b801-19f6-41ef-ad28-214bd731948f
                sourceId: 2c6991c5-c9e2-4af8-879e-29c5a9d26509
      responses:
        '200':
          description: Responses from the application.changeSource endpoint
          content:
            application/json:
              schema:
                oneOf:
                - title: Success response
                  allOf:
                  - $ref: '#/paths/~1job.info/post/responses/200/content/application~1json/schema/oneOf/0/allOf/0'
                  - type: object
                    properties:
                      results:
                        $ref: '#/webhooks/pushToHRIS/post/requestBody/content/application~1json/schema/properties/data/properties/application'
                    required:
                    - results
                - $ref: '#/paths/~1report.generate/post/responses/429/content/application~1json/schema'
  /application.changeStage:
    post:
      summary: application.changeStage
      operationId: applicationChangeStage
      description: 'Change the stage of an application


        **Requires the [`candidatesWrite`](authentication#permissions-applicationchangestage) permission.**

        '
      tags:
      - Application
      requestBody:
        content:
          application/json:
            schema:
              properties:
                applicationId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The id of the application to update the stage of
                interviewStageId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The interview stage to move the application to.
                archiveReasonId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: "Archive Reason to set when moving to an Interview Stage with type: `Archived`. \nNote: You must pass this parameter when moving to an Interview Stage with type: `Archived`\n"
                archiveEmail:
                  type: object
                  properties:
                    communicationTemplateId:
                      allOf:
                      - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                      - description: 'The id of the communication template to use for the email.

                          Note: This communication template''s intendedTypes must include: `email`.

                          '
                    sendAt:
                      type: string
                      format: date-time
                      description: 'The date and time to send the email as an ISO 8601 date and time string, e.g. `2025-02-24T08:27:01Z`.

                        If omitted, the email will be scheduled for the following morning at 9:32am in your default timezone.

                        If the time is in the past, the email will be sent immediately.

                        Note: If a timezone is not specified, timestamps will be interpreted in UTC, regardless of your timezone setting.

                        '
                  description: 'Email to send to the candidate when moving to an Interview Stage with type: `Archived`.

                    Note: If application is already archived, the email will not be sent.

                    Note: If email send fails, the application stage will not be updated. If this is the case, you can retry the request without this parameter.

                    Note: You may only pass this parameter if the application is moving to an Interview Stage with type: `Archived`.

                    '
                  required:
                  - communicationTemplateId
              required:
              - applicationId
              - interviewStageId
              example:
                applicationId: 3ae2b801-19f6-41ef-ad28-214bd731948f
                interviewStageId: 2c6991c5-c9e2-4af8-879e-29c5a9d26509
      responses:
        '200':
          description: Responses from the application.changeStage endpoint
          content:
            application/json:
              schema:
                oneOf:
                - title: Success response
                  allOf:
                  - $ref: '#/paths/~1job.info/post/responses/200/content/application~1json/schema/oneOf/0/allOf/0'
                  - type: object
                    properties:
                      results:
                        $ref: '#/webhooks/pushToHRIS/post/requestBody/content/application~1json/schema/properties/data/properties/application'
                    required:
                    - results
                - allOf:
                  - $ref: '#/paths/~1report.generate/post/responses/429/content/application~1json/schema'
                  - type: object
                    properties:
                      errors:
                        type: array
                        items:
                          type: string
                          enum:
                          - invalid_input
                          - application_not_found
                          - interview_plan_not_found
                          - interview_stage_not_found
                          - archive_reason_not_found
                          - communication_template_not_found
                          - communication_template_not_allowed
                        description: '| Error Code | Description |

                          |------------|-------------|

                          | `invalid_input` | A parameter is the wrong type |

                          | `invalid_input` | Archive fields are not allowed for non-archive stages |

                          | `invalid_input` | Archive reason ID is required for archive stages |

                          | `application_not_found` |  |

                          | `interview_plan_not_found` |  |

                          | `interview_stage_not_found` |  |

                          | `archive_reason_not_found` |  |

                          | `communication_template_not_found` |  |

                          | `communication_template_not_allowed` | Template contains unresolvable substitution tokens |

                          | `communication_template_not_allowed` | Template intended types does not include ''email'' |

                          | `communication_template_not_allowed` | [Less common] Template is archived |

                          | `communication_template_not_allowed` | [Less common] Template is a one-off template |

                          '
  /application.create:
    post:
      summary: application.create
      operationId: applicationCreate
      description: 'Consider a candidate for a job (eg when sourcing a candidate for a job posting).


        If you''re submitting an application as a job board, use the [`applicationForm.submit`](https://developers.ashbyhq.com/reference/applicationformsubmit) endpoint instead. See [Creating a custom careers page](https://developers.ashbyhq.com/docs/creating-a-custom-careers-page) for details.


        **Requires the [`candidatesWrite`](authentication#permissions-applicationcreate) permission.**


        To set values for custom fields on Applications, use the [`customFields.setValue`](https://developers.ashbyhq.com/reference/customfieldsetvalue) endpoint.

        '
      tags:
      - Application
      requestBody:
        content:
          application/json:
            schema:
              properties:
                candidateId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The id of the candidate to consider for a job
                jobId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The id of the job to consider the candidate for
                interviewPlanId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: 'The id of the interview plan to place the application in. If none is provided, the default interview plan is used.

                      '
                interviewStageId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: "The interview stage of the interview plan (either default or provided) to place the application in. \nIf none is provided, the application is placed in the first \"Lead\" stage. \nYou can also supply the special string \"FirstPreInterviewScreen\", which will choose the first pre-interview-screen stage on the specified job's interview plan.\n"
                sourceId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The source to set on the application being created.
                creditedToUserId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The id of the user the application will be credited to.
                createdAt:
                  allOf:
                  - description: 'An ISO date string to set the application''s `createdAt` timestamp. When this value isn''t provided, the `createdAt` timestamp defaults to the time the call was made.

                      '
                  - $ref: '#/paths/~1candidate.createNote/post/requestBody/content/application~1json/schema/properties/createdAt'
                applicationHistory:
                  allOf:
                  - type: array
                    description: An array of objects representing the application history.
                    items:
                      type: object
                      properties:
                        stageId:
                          allOf:
                          - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                          - description: The ID of the interview stage for this history event. This stage must belong to the interview plan associated with the application.
                        stageNumber:
                          allOf:
                          - type: integer
                          - description: The sort order of this event. 0 is the first, the highest number will be the current stage.
                        enteredStageAt:
                          allOf:
                          - $ref: '#/paths/~1candidate.addEmailMessage/post/requestBody/content/application~1json/schema/properties/sentAt/allOf/0'
                          - description: An ISO date string representing the time the application entered this stage.
                        archiveReasonId:
                          allOf:
                          - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                          - description: The ID of the archive reason. If the interview stage is an `Archived` stage type, this field is required.
                      required:
                      - stageId
                      - stageNumber
                      - enteredStageAt
                  - description: 'An array of objects representing the application history.

                      '
              required:
              - candidateId
              - jobId
              example:
                candidateId: 3ae2b801-19f6-41ef-ad28-214bd731948f
                jobId: 2c6991c5-c9e2-4af8-879e-29c5a9d26509
      responses:
        '200':
          description: Responses from the application.create endpoint
          content:
            application/json:
              schema:
                oneOf:
                - title: Success response
                  allOf:
                  - $ref: '#/paths/~1job.info/post/responses/200/content/application~1json/schema/oneOf/0/allOf/0'
                  - type: object
                    properties:
                      results:
                        $ref: '#/webhooks/pushToHRIS/post/requestBody/content/application~1json/schema/properties/data/properties/application'
                    required:
                    - results
                - $ref: '#/paths/~1report.generate/post/responses/429/content/application~1json/schema'
  /applicationForm.submit:
    post:
      summary: applicationForm.submit
      description: 'Submit an application for a job posting.


        **Requires the [`candidatesWrite`](authentication#permissions-applicationformsubmit) permission.**


        The Content-Type of this request must be `multipart/form-data` or `application/json`.


        When using `application/json`, file fields should contain a handle string obtained from [`file.createFileUploadHandle`](https://developers.ashbyhq.com/reference/filecreatefileuploadhandle) with `fileUploadContext` set to `ApplicationForm`. This allows files to be uploaded directly to storage, bypassing the need to send file bytes through the API.


        When using `multipart/form-data`, file fields should reference a file part included in the multipart request body (existing behavior).


        **Important:** Please ensure that you check the response''s `success` field and display any validation errors to candidates if it is `false`. Not doing so will result in applications not being recorded, without any notification to the candidate prompting them to resubmit. For testing purposes, you can simulate a validation failure by submitting the email address `[email protected]`.


        **Note: The requests generated from this documentation will not work for this endpoint.**


        The values accepted for each field depend on the type of field that''s being filled out:

        - `Boolean` - A boolean value

        - `Date` - A date string in the format YYYY-MM-DD

        - `Email` - A valid email address

        - `Number` - An integer

        - `RichText` - We do not support submitting rich text documents via the API but we do support submitting plain text values for these fields. Plain text values must be submitted in the format `{ type: "PlainText", value: "A plain text string" }`

        - `Score` - An integer between 1 and 4 submitted in the format `{ score: 4 }`

        - `Phone`, `String` A string

        - `ValueSelect` - A string that matches the value of one of the ValueSelect field''s selectable options

        - `MultiValueSelect` - An array of strings that exist in the MultiValueSelect field''s selectable options

        - `Location` - An object with the following properties: `{ country: "USA", city: "San Francisco", region: "California" }`. You may provide any combination of these properties and we will attempt to geocode the location. For best results, provide all three properties.

        - `EducationHistory` - [Early Access] An array of objects with the following properties: `{ schoolName: "University of California, Berkeley", degree: "Bachelor of Science", major: "Computer Science", startDate: "2020-09-01", endDate: "2024-05-15", isCurrent: true }`. Only `schoolName` is required. We will attempt to match the school name to a known school in our database. If `isCurrent` is true, `endDate` must not be provided.

        '
      operationId: applicationformsubmit
      tags:
      - Application Form
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - jobPostingId
              - applicationForm
              properties:
                jobPostingId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The id of the job posting to submit an application for
                applicationForm:
                  $ref: '#/paths/~1offer.create/post/requestBody/content/application~1json/schema/properties/offerForm'
                utmData:
                  type: object
                  properties:
                    utm_source:
                      type: string
                    utm_campaign:
                      type: string
                    utm_medium:
                      type: string
                    utm_term:
                      type: string
                    utm_content:
                      type: string
                tagIds:
                  type: array
                  description: The ids of the tags to apply to the candidate
                  items:
                    allOf:
                    - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                allowSubmissionForUnpublishedJobPosting:
                  type: boolean
                  example: true
                  description: Defaults to true. If you are running a custom built careers page that is statically generated, you may want to set this to true to allow applications to be submitted in the time a job is unpublished and your careers page is refreshed. If set to false, applications submitted for unpublished job postings will return a `job_posting_not_published` error.
          multipart/form-data:
            schema:
              type: object
              required:
              - jobPostingId
              - applicationForm
              properties:
                jobPostingId:
                  allOf:
                  - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  - description: The id of the job posting to submit an application for
                applicationForm:
                  $ref: '#/paths/~1offer.create/post/requestBody/content/application~1json/schema/properties/offerForm'
                utmData:
                  type: object
                  properties:
                    utm_source:
                      type: string
                    utm_campaign:
                      type: string
                    utm_medium:
                      type: string
                    utm_term:
                      type: string
                    utm_content:
                      type: string
                tagIds:
                  type: array
                  description: The ids of the tags to apply to the candidate
                  items:
                    allOf:
                    - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                allowSubmissionForUnpublishedJobPosting:
                  type: boolean
                  example: true
                  description: Defaults to true. If you are running a custom built careers page that is statically generated, you may want to set this to true to allow applications to be submitted in the time a job is unpublished and your careers page is refreshed. If set to false, applications submitted for unpublished job postings will return a `job_posting_not_published` error.
                <file key>:
                  type: string
                  description: Any file referenced in the `applicationForm`. The name of this field must exactly match the `value` on the `fieldSubmission` that references this file.
                  format: binary
      responses:
        '200':
          description: Responses from the applicationFeedback.submit endpoint
          content:
            application/json:
              schema:
                oneOf:
                - title: Success response
                  allOf:
                  - $ref: '#/paths/~1job.info/post/responses/200/content/application~1json/schema/oneOf/0/allOf/0'
                  - type: object
                    properties:
                      results:
                        type: object
                        properties:
                          submittedFormInstance:
                            type: object
                            properties:
                              id:
                                $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                              formDefinition:
                                $ref: '#/paths/~1offer.start/post/responses/200/content/application~1json/schema/oneOf/0/allOf/1/properties/results/properties/formDefinition'
                              submittedValues:
                                type: object
                                example:
                                  _systemfield_name: Gob Bluth
                            required:
                            - id
                            - formDefinition
                            - submittedValues
                          formMessages:
                            allOf:
                            - type: object
                              description: Messages related to the application form submission. Check if the application was blocked before submitting any surveys.
                              properties:
                                blocked:
                                  type: boolean
                                  description: Whether the application was blocked due to configured application limits (eg too many applications submitted for a single candidate). If true, do not attempt to submit any surveys, if any.
                                  example: true
                                blockMessageForCandidateHtml:
                                  type: string
                                  description: A message to display to the candidates regarding the application limits. If there is no message, then the candidate should not be informed that they were blocked.
                                  example: '<div><p>Please Note: we have set up limits for applications for this role. Candidates may not apply more than 2 times in any 60 day span for any job in the Application Limit Group.</p></div>

                                    '
                              required:
                              - blocked
                            - description: "Contains information about the form submission. When `blocked` is true, \nthe application was blocked by organizational rules and no Application \nrecord was created. Do not attempt to call `application.info` with the \n`submittedFormInstanceId` as it will return an `application_blocked` error. \nThe submission is saved as a blocked submission and can be reviewed by \nadministrators.\n"
                        required:
                        - submittedFormInstance
                        - formMessages
                    required:
                    - results
                - $ref: '#/paths/~1report.generate/post/responses/429/content/application~1json/schema'
  /applicationHiringTeamRole.list:
    post:
      summary: applicationHiringTeamRole.list
      operationId: applicationHiringTeamRoleList
      description: 'Gets all available hiring team roles for applications in the organization.


        **Requires the [`candidatesRead`](authentication#permissions-applicationHiringTeamRoleList) permission.**

        '
      tags:
      - Application Hiring Team Role
      responses:
        '200':
          description: Responses from the applicationHiringTeamRole.list endpoint
          content:
            application/json:
              schema:
                oneOf:
                - allOf:
                  - properties:
                      results:
                        type: array
                        items:
                          allOf:
                          - type: object
                            properties:
                              id:
                                $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                              title:
                                type: string
                            required:
                            - id
                            - title
                  required:
                  - results
                - $ref: '#/paths/~1report.generate/post/responses/429/content/application~1json/schema'
  /application.info:
    post:
      summary: application.info
      operationId: applicationInfo
      description: 'Fetch application details by application id or by submitted form instance id (which is return by the `applicationForm.submit` endpoint). If both applicationId and submittedFormInstanceId are provided, we will lookup by applicationId.


        **Requires the [`candidatesRead`](authentication#permissions-applicationinfo) permission.**

        '
      tags:
      - Application
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
              - type: object
                properties:
                  applicationId:
                    allOf:
                    - description: The id of the application to fetch.
                    - $ref: '#/paths/~1interviewerPool.addUser/post/requestBody/content/application~1json/schema/properties/userId'
                  expand:
                    type: array
                    description: "Choose to expand the result and include additional data for related objects. \n"
                    items:
                      type: string
                      enum:
                      - openings
                      - applicationFormSubmissions
                      - referrals
                required:
                - applicationId
              - type: object
                properties:
                  submittedFormInstanceId:
                    allOf:
                    - description: The id of 

# --- truncated at 32 KB (641 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/ashby-hq/refs/heads/main/openapi/ashby-openapi.yml