Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/chamals3n4/OpenATS/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Offers API handles the complete lifecycle of candidate job offers, from initial creation through acceptance or decline. Offers can be generated from templates, customized per candidate, and tracked through various status transitions. Offer Status Flow:
draft → sent → pending → accepted/declined/withdrawn

Create Offer

Generate a new offer for a candidate. The offer can optionally use a template and will inherit salary details from the job if not specified.
POST /offers
curl -X POST http://localhost:8080/api/offers \
  -H "Content-Type: application/json" \
  -d '{
    "candidateId": 42,
    "jobId": 5,
    "templateId": 1,
    "salary": 150000,
    "currency": "USD",
    "payFrequency": "yearly",
    "startDate": "2024-04-15",
    "expiryDate": "2024-04-01",
    "createdBy": 1
  }'
Request Body:
FieldTypeRequiredDescription
candidateIdintegerYesID of the candidate receiving the offer
jobIdintegerYesID of the job position
templateIdintegerNoTemplate to use for offer letter (null for no template)
salarynumberNoOffer salary amount (inherits from job if not specified)
currencystringNo3-letter currency code (e.g., “USD”, “EUR”, “GBP”)
payFrequencyenumNoPayment frequency: hourly, daily, weekly, monthly, yearly
startDatestringNoProposed employment start date (ISO 8601 format: YYYY-MM-DD)
expiryDatestringNoOffer expiration date (ISO 8601 format: YYYY-MM-DD)
createdByintegerNoUser ID of offer creator (defaults to 1)
Response:
{
  "data": {
    "id": 12,
    "candidateId": 42,
    "jobId": 5,
    "templateId": 1,
    "salary": 150000,
    "currency": "USD",
    "payFrequency": "yearly",
    "startDate": "2024-04-15",
    "expiryDate": "2024-04-01",
    "status": "draft",
    "renderedHtml": null,
    "createdBy": 1,
    "createdAt": "2024-03-15T10:30:00Z",
    "updatedAt": "2024-03-15T10:30:00Z"
  }
}

List Offers by Job

Retrieve all offers associated with a specific job opening.
GET /offers/job/:jobId
curl -X GET http://localhost:8080/api/offers/job/5 \
  -H "Content-Type: application/json"
Path Parameters:
ParameterTypeRequiredDescription
jobIdintegerYesJob opening ID
Response:
{
  "data": [
    {
      "id": 12,
      "candidateId": 42,
      "candidateName": "John Doe",
      "jobId": 5,
      "jobTitle": "Senior Backend Engineer",
      "salary": 150000,
      "currency": "USD",
      "payFrequency": "yearly",
      "status": "sent",
      "createdAt": "2024-03-15T10:30:00Z",
      "expiryDate": "2024-04-01"
    },
    {
      "id": 11,
      "candidateId": 38,
      "candidateName": "Jane Smith",
      "jobId": 5,
      "jobTitle": "Senior Backend Engineer",
      "salary": 145000,
      "currency": "USD",
      "payFrequency": "yearly",
      "status": "accepted",
      "createdAt": "2024-03-10T14:20:00Z",
      "expiryDate": "2024-03-25"
    }
  ]
}

Get Offer by ID

Retrieve full details for a specific offer, including rendered HTML if available.
GET /offers/:id
curl -X GET http://localhost:8080/api/offers/12 \
  -H "Content-Type: application/json"
Path Parameters:
ParameterTypeRequiredDescription
idintegerYesOffer ID
Response:
{
  "data": {
    "id": 12,
    "candidateId": 42,
    "candidate": {
      "id": 42,
      "firstName": "John",
      "lastName": "Doe",
      "email": "john.doe@example.com",
      "phone": "+1 555 123 4567"
    },
    "jobId": 5,
    "job": {
      "id": 5,
      "title": "Senior Backend Engineer",
      "department": "Engineering",
      "location": "San Francisco, CA (Remote)"
    },
    "templateId": 1,
    "template": {
      "id": 1,
      "name": "Standard Engineering Offer",
      "type": "offer"
    },
    "salary": 150000,
    "currency": "USD",
    "payFrequency": "yearly",
    "startDate": "2024-04-15",
    "expiryDate": "2024-04-01",
    "status": "sent",
    "renderedHtml": "<div class='offer-letter'>...</div>",
    "createdBy": 1,
    "createdAt": "2024-03-15T10:30:00Z",
    "updatedAt": "2024-03-15T11:00:00Z",
    "sentAt": "2024-03-15T11:00:00Z"
  }
}

Update Offer

Modify offer details such as salary, dates, or template. Cannot update offers that have been accepted.
PUT /offers/:id
curl -X PUT http://localhost:8080/api/offers/12 \
  -H "Content-Type: application/json" \
  -d '{
    "salary": 155000,
    "startDate": "2024-04-22",
    "expiryDate": "2024-04-08"
  }'
Path Parameters:
ParameterTypeRequiredDescription
idintegerYesOffer ID
Request Body: All fields are optional. Only include fields you want to update.
FieldTypeDescription
templateIdintegerTemplate ID (null to remove template)
salarynumberOffer salary amount
currencystring3-letter currency code
payFrequencyenumPayment frequency: hourly, daily, weekly, monthly, yearly
startDatestringEmployment start date (YYYY-MM-DD)
expiryDatestringOffer expiration date (YYYY-MM-DD)
statusenumOffer status: draft, sent, pending, accepted, declined, withdrawn
renderedHtmlstringManually set rendered HTML (overrides template rendering)
Response:
{
  "data": {
    "id": 12,
    "candidateId": 42,
    "jobId": 5,
    "templateId": 1,
    "salary": 155000,
    "currency": "USD",
    "payFrequency": "yearly",
    "startDate": "2024-04-22",
    "expiryDate": "2024-04-08",
    "status": "sent",
    "renderedHtml": "<div class='offer-letter'>...</div>",
    "createdBy": 1,
    "createdAt": "2024-03-15T10:30:00Z",
    "updatedAt": "2024-03-16T09:15:00Z",
    "sentAt": "2024-03-15T11:00:00Z"
  }
}

Update Offer Status

Transition an offer through its lifecycle states. This is the preferred method for status changes.
PATCH /offers/:id/status
curl -X PATCH http://localhost:8080/api/offers/12/status \
  -H "Content-Type: application/json" \
  -d '{
    "status": "accepted"
  }'
Path Parameters:
ParameterTypeRequiredDescription
idintegerYesOffer ID
Request Body:
FieldTypeRequiredDescription
statusenumYesNew status: draft, sent, pending, accepted, declined, withdrawn
Status Definitions:
StatusDescription
draftOffer is being prepared, not yet sent to candidate
sentOffer has been sent to candidate
pendingCandidate is reviewing the offer
acceptedCandidate has accepted the offer
declinedCandidate has declined the offer
withdrawnCompany has withdrawn the offer
Response:
{
  "data": {
    "id": 12,
    "candidateId": 42,
    "jobId": 5,
    "status": "accepted",
    "updatedAt": "2024-03-16T14:30:00Z",
    "acceptedAt": "2024-03-16T14:30:00Z"
  }
}

Delete Offer

Void and permanently delete an offer. This action cannot be undone.
DELETE /offers/:id
curl -X DELETE http://localhost:8080/api/offers/12 \
  -H "Content-Type: application/json"
Path Parameters:
ParameterTypeRequiredDescription
idintegerYesOffer ID
Response:
{
  "data": {
    "id": 12,
    "candidateId": 42,
    "jobId": 5,
    "status": "withdrawn",
    "deletedAt": "2024-03-16T15:00:00Z"
  }
}

Complete Offer Flow Example

Here’s a typical workflow for creating and managing an offer:
1

Create Draft Offer

curl -X POST http://localhost:8080/api/offers \
  -H "Content-Type: application/json" \
  -d '{
    "candidateId": 42,
    "jobId": 5,
    "templateId": 1,
    "salary": 150000,
    "currency": "USD",
    "payFrequency": "yearly",
    "startDate": "2024-04-15",
    "expiryDate": "2024-04-01"
  }'
2

Review and Update if Needed

curl -X PUT http://localhost:8080/api/offers/12 \
  -H "Content-Type: application/json" \
  -d '{
    "salary": 155000
  }'
3

Send to Candidate

curl -X PATCH http://localhost:8080/api/offers/12/status \
  -H "Content-Type: application/json" \
  -d '{"status": "sent"}'
4

Track Candidate Decision

# Candidate accepts
curl -X PATCH http://localhost:8080/api/offers/12/status \
  -H "Content-Type: application/json" \
  -d '{"status": "accepted"}'

# Or candidate declines
curl -X PATCH http://localhost:8080/api/offers/12/status \
  -H "Content-Type: application/json" \
  -d '{"status": "declined"}'

Error Responses

Validation Error (400):
{
  "error": "Validation failed",
  "details": {
    "salary": ["Expected number, received string"],
    "currency": ["String must contain exactly 3 character(s)"]
  }
}
Not Found (404):
{
  "error": "Offer not found"
}
Constraint Error (400):
{
  "error": "Cannot update accepted offer"
}

Build docs developers (and LLMs) love