> ## Documentation Index
> Fetch the complete documentation index at: https://docs.join.tl/llms.txt
> Use this file to discover all available pages before exploring further.

# Receive a signed Greenhouse webhook

> Validates Signature over the raw body and requires a durable Greenhouse-Event-ID for replay protection.



## OpenAPI

````yaml /specs/openapi/greenhouse-v1.openapi.yaml post /api/apps/greenhouse/v1/webhook/{installationId}
openapi: 3.1.2
info:
  title: Jointl Greenhouse Integration API
  version: 1.0.0
  description: >-
    Jointl endpoints used by Greenhouse Recruiting webhooks and the
    assessment-partner integration.
  contact:
    name: Jointl Support
    url: https://join.tl
servers:
  - url: https://api.join.tl
    description: Jointl production API
security: []
externalDocs:
  description: Greenhouse Harvest API documentation for upstream dependencies
  url: https://developers.greenhouse.io/harvest.html
paths:
  /api/apps/greenhouse/v1/webhook/{installationId}:
    post:
      summary: Receive a signed Greenhouse webhook
      description: >-
        Validates Signature over the raw body and requires a durable
        Greenhouse-Event-ID for replay protection.
      operationId: receiveGreenhouseWebhook
      parameters:
        - name: installationId
          in: path
          required: true
          schema:
            type: string
            pattern: ^[23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz]{17}$
        - name: Greenhouse-Event-ID
          in: header
          required: true
          schema:
            type: string
          description: Stable event identity. Preserve it unchanged across retries.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - type: object
                  properties:
                    action:
                      type: string
                      const: ping
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: job_created
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: job_deleted
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: new_candidate_application
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: application_updated
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: candidate_stage_change
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: hire_candidate
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: unhire_candidate
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: reject_candidate
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: unreject_candidate
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
                - type: object
                  properties:
                    action:
                      type: string
                      const: delete_candidate
                    payload:
                      type: object
                      additionalProperties: true
                  required:
                    - action
                    - payload
                  additionalProperties: false
              discriminator:
                propertyName: action
            examples:
              application_updated:
                summary: application_updated
                value:
                  action: application_updated
                  payload:
                    application:
                      candidate:
                        email_addresses:
                          - type: work
                            value: ada@example.test
                        first_name: Ada
                        id: 20001
                        last_name: Example
                        photo_url: https://example.com/images/ada.png
                        url: https://example.com/candidates/20001
                      current_stage:
                        id: 40001
                        name: Jointl Review
                      id: 10001
                      jobs:
                        - id: 30001
                      prospect: false
                      status: active
              candidate_stage_change:
                summary: candidate_stage_change
                value:
                  action: candidate_stage_change
                  payload:
                    application:
                      candidate:
                        email_addresses:
                          - type: work
                            value: ada@example.test
                        first_name: Ada
                        id: 20001
                        last_name: Example
                        photo_url: https://example.com/images/ada.png
                        url: https://example.com/candidates/20001
                      current_stage:
                        id: 40001
                        name: Jointl Review
                      id: 10001
                      jobs:
                        - id: 30001
                      prospect: false
                      status: active
              delete_candidate:
                summary: delete_candidate
                value:
                  action: delete_candidate
                  payload:
                    person:
                      id: 20001
              hire_candidate:
                summary: hire_candidate
                value:
                  action: hire_candidate
                  payload:
                    application:
                      candidate:
                        id: 20001
                      id: 10001
              job_created:
                summary: job_created
                value:
                  action: job_created
                  payload:
                    job:
                      id: 30001
                      name: Example Software Engineer
              job_deleted:
                summary: job_deleted
                value:
                  action: job_deleted
                  payload:
                    job:
                      id: 30001
                      name: Example Software Engineer
              new_candidate_application:
                summary: new_candidate_application
                value:
                  action: new_candidate_application
                  payload:
                    application:
                      candidate:
                        email_addresses:
                          - type: work
                            value: ada@example.test
                        first_name: Ada
                        id: 20001
                        last_name: Example
                        photo_url: https://example.com/images/ada.png
                        url: https://example.com/candidates/20001
                      current_stage:
                        id: 40001
                        name: Jointl Review
                      id: 10001
                      jobs:
                        - id: 30001
                      prospect: false
                      status: active
              ping:
                summary: ping
                value:
                  action: ping
                  payload: {}
              reject_candidate:
                summary: reject_candidate
                value:
                  action: reject_candidate
                  payload:
                    application:
                      candidate:
                        id: 20001
                      id: 10001
              unhire_candidate:
                summary: unhire_candidate
                value:
                  action: unhire_candidate
                  payload:
                    application:
                      candidate:
                        id: 20001
                      id: 10001
              unreject_candidate:
                summary: unreject_candidate
                value:
                  action: unreject_candidate
                  payload:
                    application:
                      candidate:
                        id: 20001
                      id: 10001
      responses:
        '200':
          description: Processed or exact duplicate acknowledged.
          content:
            text/plain:
              schema:
                type: string
              example: OK
        '400':
          description: Invalid JSON object, signature, event identity, or action.
          content:
            text/plain:
              schema:
                type: string
              example: Invalid signature
        '404':
          description: Installation not found. Empty body.
        '409':
          description: Event ID was reused with a different body.
          content:
            text/plain:
              schema:
                type: string
              example: Webhook event conflict
        '413':
          description: Request exceeds one MiB.
          content:
            text/plain:
              schema:
                type: string
              example: Request body is too large
        '429':
          description: Rate limited.
          headers:
            Retry-After:
              schema:
                type: integer
        '500':
          description: Processing failed.
          content:
            text/plain:
              schema:
                type: string
              example: Greenhouse webhook processing failed.
        '503':
          description: The same event is already processing.
          content:
            text/plain:
              schema:
                type: string
              example: Webhook event is already processing
      security:
        - GreenhouseWebhookSignature: []
components:
  securitySchemes:
    GreenhouseWebhookSignature:
      type: apiKey
      in: header
      name: Signature
      description: Greenhouse signature verified against the installation webhook secret.

````