---
title: "Create offer"
method: POST
path: "/v3/offers"
tags: ["Offers"]
---

# Create offer

`POST /v3/offers`

Create a new offer on an existing application. `application_id` is always required; `starts_on` and `custom_fields` (compensation components plus any offer custom fields configured on the hiring plan) are optional in the schema, but organization configuration may require more: offer custom fields marked as required must be provided in `custom_fields` (a 422 response names the missing fields), and `starts_on` must be provided when the Start Date field is marked required. Discover the organization's offer fields — including `required` and `name_key` — via `GET /v3/custom_fields?field_type=offer&active=true`. The new offer is created with `status=Created` at `version=1`. If the application already has an offer, the submission is applied to the same offer chain rather than creating a competing record: a new version is created — and the prior version marked `Deprecated` — only when a version-triggering field changes, namely `starts_on` (when your organization enables offer versioning on start-date changes) or a compensation/offer custom field configured to trigger a new version; otherwise the current offer is updated in place. Approval flows configured for the hiring plan are attached automatically — partners must drive the approval through `/v3/approval_flows` before the offer can be sent to the candidate.

## Request body

- object
  - `application_id` integer, required — Id of the application this offer is being extended on. Required.
  - `starts_on` string, date — Candidate's proposed start date, in ISO 8601 (YYYY-MM-DD). Required when the organization marks the Start Date offer field as required.
  - `custom_fields` union[] — Values for the offer's custom fields, including compensation components (base pay, equity, bonus, etc.). Each entry sets one custom field by name or id; only fields configured on the application's hiring plan apply. Offer custom fields the organization marks as required must be included, otherwise the request fails with a 422 naming the missing fields. List the organization's offer fields, including `required` and `name_key`, via `GET /v3/custom_fields?field_type=offer&active=true`.
    - union
      - object
        - `name_key` string, required — Required if custom_field_id is not provided. Exactly one of name_key or custom_field_id must be specified.
        - `custom_field_id` integer — Required if name_key is not provided. Exactly one of name_key or custom_field_id must be specified.
        - `value` union
          - string
          - string
          - string
          - string
          - string
          - boolean
          - number — User ID
          - union
            - string[]
            - number[]
          - number
          - object
            - `amount` number, required
            - `currency_code` string, required
            - `rationale` string
            - `frequency` string
          - object
            - `min_amount` number, required
            - `max_amount` number, required
            - `currency_code` string, required
          - object
            - `min_value` number, required
            - `max_value` number, required
      - object
        - `name_key` string — Required if custom_field_id is not provided. Exactly one of name_key or custom_field_id must be specified.
        - `custom_field_id` integer, required — Required if name_key is not provided. Exactly one of name_key or custom_field_id must be specified.
        - `value` union
          - string
          - string
          - string
          - string
          - string
          - boolean
          - number — User ID
          - union
            - string[]
            - number[]
          - number
          - object
            - `amount` number, required
            - `currency_code` string, required
            - `rationale` string
            - `frequency` string
          - object
            - `min_amount` number, required
            - `max_amount` number, required
            - `currency_code` string, required
          - object
            - `min_value` number, required
            - `max_value` number, required

## Response `201`

Successful

- object
  - `id` integer
  - `created_at` string, date-time
  - `updated_at` string, date-time
  - `version` integer — Revision number of this offer within its application. Greenhouse creates a new offer row (incrementing `version`) whenever a tracked field on an existing offer changes — typically `starts_on`, `opening_id`, or a custom field configured to trigger a new version. Pair with `current_only=true` to filter the list endpoint down to the latest version per application.
  - `application_id` integer — Id of the application this offer is extended on. Every offer belongs to exactly one application; the offer is voided if the application is rejected or deleted.
  - `job_id` integer — Id of the job this offer's application is on.
  - `candidate_id` integer — Id of the candidate (person) receiving this offer. Resolved through the offer's application.
  - `opening_id` integer, nullable — Id of the specific opening this offer is being extended for. `null` when the offer has not yet been linked to an opening.
  - `status` 'Created' | 'Accepted' | 'Rejected' | 'Deprecated' — Lifecycle status of the offer. `Created` for offers still being drafted or pending approval, `Accepted` once the candidate accepts, `Rejected` if declined or withdrawn, and `Deprecated` for superseded prior versions (a new offer version replaces an earlier one with this status).
  - `starts_on` string, date, nullable — Candidate's proposed start date, in ISO 8601 (YYYY-MM-DD). `null` when no start date has been set on the offer.
  - `sent_on` string, date, nullable — Date the offer was sent to the candidate, in ISO 8601 (YYYY-MM-DD). `null` until the offer has been sent.
  - `resolved_at` string, date-time, nullable — Timestamp the offer was resolved (`Accepted` or `Rejected`), in ISO 8601. Date updates submitted through `PATCH /v3/offers/{id}` are normalized to noon UTC on the supplied date. `null` while the offer is still `Created` or has been superseded as `Deprecated` without a resolution.
  - `custom_fields` object, nullable

## Other responses

- `401` — Unauthorized
- `403` — Forbidden
- `422` — Unprocessable Content

---

[API](https://skmtc.dev/greenhouse/apis/auth-api.md) · [All operations](https://skmtc.dev/greenhouse/apis/auth-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/greenhouse/auth-api/revisions/9517a2e54640/schema)
