> This page is for API, version 2026-01-01 (Stable) (default).
> For other versions, use one of these documentation indexes:
> - 2026-01-01 (Stable) (default): https://developer.deel.com/api/stable/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.deel.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.deel.com/_mcp/server.

# List job openings

GET https://api.letsdeel.com/rest/ats/openings

Lists the headcount openings (requisitions), that is the positions that jobs are hiring for. Use it to review that headcount and to see which hire filled each opening. Callers with restricted access see only the openings they may view.

 **Token scopes**: `ats:read`, `worker:read`

Reference: https://developer.deel.com/api/reference/endpoints/ats/list-openings-v-2026-06-15

## Authentication

- `Authorization` header (bearer token, required) — ## Authentication The Deel API uses bearer tokens to authenticate requests. All API calls must be made over HTTPS — calls over plain HTTP or without authentication will fail. ```curl curl -X GET 'https://api.letsdeel.com/rest/v2/contracts' \ -H 'Authorization: Bearer YOUR-TOKEN-HERE' ``` [Learn more about authentication](/api/authentication)
- `Authorization` header (bearer token, required) — Standard OAuth2 security scheme based on https://swagger.io/docs/specification/authentication/

## Servers

- `https://api.letsdeel.com/rest` (Production, default)
- `https://api-staging.letsdeel.com/rest` (Demo)

## Request

### Query parameters

- `cursor` (string, optional) — Pagination cursor returned by a previous response.
- `limit` (integer, optional) — Maximum number of openings to return per page.
- `status` (list of enum, optional) — Filter openings by one or more statuses.
  - Allowed values: `DRAFT`, `OPEN`, `FILLED`, `CLOSED`, `WAITING_FOR_APPROVAL`, `APPROVED`, `NOT_APPROVED`, `ARCHIVED`
- `team_ids` (list of string, optional) — Filter openings by team IDs.
- `location_ids` (list of string, optional) — Filter openings by location IDs.
- `job_ids` (list of string, optional) — Filter openings by linked job IDs.
- `tag_ids` (list of string, optional) — Filter openings by tag IDs.
- `tag_ids_operator` (enum, optional) — Operator for tag_ids filter. 'ANY' returns openings with at least one matching tag; 'ALL' returns openings with all specified tags. Defaults to 'ANY'.
  - Allowed values: `ANY`, `ALL`

## Response

### 200

Paginated list of job openings.

- `data` (list of AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItems, required) — Page of openings.
- `has_more` (boolean, required) — Whether more pages are available beyond the current page.
- `next_cursor` (string, required, nullable) — Cursor to fetch the next page; null when there are no more pages.
- `total_count` (integer, required) — Total number of openings matching the filters.

## Errors

### 400 Bad Request Error

Operation failed.

- `errors` (list of AtsOpeningsGetResponsesContentApplicationJsonSchemaErrorsItems, required) — List of error objects

### 401 Unauthorized Error

Operation failed.

- `request` (ApiErrorRequest, optional)
- `errors` (list of ApiError, optional)

### 403 Forbidden Error

Forbidden. ATS is not enabled for this organization or insufficient permissions.

- `errors` (list of AtsOpeningsGetResponsesContentApplicationJsonSchemaErrorsItems, required) — List of error objects

### 404 Not Found Error

Operation failed.

- `request` (ApiErrorRequest, optional)
- `errors` (list of ApiError, optional)

### 500 Internal Server Error

Operation failed.

- `errors` (list of AtsOpeningsGetResponsesContentApplicationJsonSchemaErrorsItems, required) — List of error objects

## Types

### AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItems

- `id` (string, required) — Unique identifier of the opening.
- `title` (string, required) — Title of the job opening.
- `status` (enum, required) — Current lifecycle status of the opening.
  - Allowed values: `DRAFT`, `OPEN`, `FILLED`, `CLOSED`, `WAITING_FOR_APPROVAL`, `APPROVED`, `NOT_APPROVED`, `ARCHIVED`
- `created_at` (string, required) — ISO 8601 datetime when the opening was created.
- `updated_at` (string, required) — ISO 8601 datetime when the opening was last updated.
- `opening_prefix` (string, required) — Prefix of the opening identifier (e.g. ENG in ENG-42).
- `opening_type_slug` (enum, required) — Whether this opening is for a new hire or a backfill.
  - Allowed values: `NEW_HIRE`, `BACKFILL`
- `opening_numeric_id` (integer, required) — Numeric part of the opening identifier (e.g. 42 in ENG-42).
- `team` (AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsTeam, optional, nullable) — Team details.
- `job_ids` (list of string, optional) — IDs of jobs linked to this opening.
- `team_id` (string, optional, nullable) — ID of the team this opening belongs to.
- `location` (AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsLocation, optional, nullable) — Location details.
- `location_id` (string, optional, nullable) — ID of the location associated with the opening.
- `employment_type` (AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsEmploymentType, optional, nullable) — Employment type details.
- `filled_by_offer` (AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsFilledByOffer, optional, nullable) — The accepted offer that filled this opening (latest ACCEPTED offer by update time). Null unless the opening is filled with an accepted offer. Contains no compensation data.
- `is_confidential` (boolean, optional) — Whether this opening is marked confidential.
- `target_hire_date` (string, optional, nullable) — Target date by which the opening should be filled (ISO 8601).
- `target_start_date` (string, optional, nullable) — Target start date for the new hire (ISO 8601).
- `employment_type_id` (string, optional, nullable) — ID of the employment type associated with the opening.
- `compensation_period` (string, optional, nullable) — Compensation period (e.g. yearly, monthly).
- `filled_by_application` (AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsFilledByApplication, optional, nullable) — The application that filled this opening, including the hired candidate name. Null unless the opening is filled.
- `max_compensation_amount` (string, optional, nullable) — Maximum compensation amount as a decimal string.
- `min_compensation_amount` (string, optional, nullable) — Minimum compensation amount as a decimal string.
- `filled_by_application_id` (string, optional, nullable) — ID of the application that filled this opening, if any.
- `compensation_currency_iso_code` (string, optional, nullable) — ISO 4217 currency code for compensation.
- `created_by_hris_organization_user_id` (string, optional, nullable) — HRIS organization user ID of the user who created this opening.
- `updated_by_hris_organization_user_id` (string, optional, nullable) — HRIS organization user ID of the user who last updated this opening.

### AtsOpeningsGetResponsesContentApplicationJsonSchemaErrorsItems

- `code` (string, required) — Machine-readable error code
- `message` (string, required) — Human-readable error message
- `field` (string, optional) — Request field related to the error, if applicable

### ApiErrorRequest

- `method` (string, optional) — The HTTP method of the failed request
- `url` (string, optional) — The relative URL of the failed request
- `status` (double, optional) — The status code of the response
- `api_req_id` (string, optional) — The request ID of the failed request
- `docs` (string, optional) — A link to the official documentation for the requested endpoint resource
- `source` (string, optional) — The source handler which produced the returned error
- `code` (double, optional) — The code of the source handler which produced the returned error

### ApiError

- `message` (string, optional) — A description of the returned error
- `path` (string, optional) — The JSON path where input validation failed

### AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsTeam

Team details.

- `id` (string, optional) — Unique identifier of the team.
- `name` (string, optional) — Name of the team.

### AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsLocation

Location details.

- `id` (string, optional) — Unique identifier of the location.
- `name` (string, optional) — Name of the location.
- `country` (string, optional, nullable) — ISO 3166-1 alpha-2 country code of the location.

### AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsEmploymentType

Employment type details.

- `id` (string, optional) — Unique identifier of the employment type.
- `name` (string, optional) — Name of the employment type.

### AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsFilledByOffer

The accepted offer that filled this opening (latest ACCEPTED offer by update time). Null unless the opening is filled with an accepted offer. Contains no compensation data.

- `start_date` (string, optional) — Start date from the accepted offer (ISO 8601).
- `offer_status_enum` (enum, optional) — Status of the filling offer. This object is only present for the accepted offer that filled the opening, so the value is always ACCEPTED.
  - Allowed values: `ACCEPTED`

### AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsFilledByApplication

The application that filled this opening, including the hired candidate name. Null unless the opening is filled.

- `id` (string, optional) — ID of the application that filled this opening.
- `candidate` (AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsFilledByApplicationCandidate, optional, nullable) — Minimal identity of the hired candidate.

### AtsOpeningsGetResponsesContentApplicationJsonSchemaDataItemsFilledByApplicationCandidate

Minimal identity of the hired candidate.

- `last_name` (string, optional) — Last name of the hired candidate.
- `first_name` (string, optional) — First name of the hired candidate.

## Examples

**Response**

```json
{
  "data": [
    {
      "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "title": "Senior Software Engineer",
      "status": "OPEN",
      "created_at": "2026-01-15T08:00:00Z",
      "updated_at": "2026-01-20T14:30:00Z",
      "opening_prefix": "ENG",
      "opening_type_slug": "NEW_HIRE",
      "opening_numeric_id": 42,
      "team": {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "name": "Backend Engineering"
      },
      "job_ids": [
        "f47ac10b-58cc-4372-a567-0e02b2c3d479"
      ],
      "team_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "location": {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "name": "New York",
        "country": "US"
      },
      "location_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "employment_type": {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "name": "Full-time"
      },
      "filled_by_offer": {
        "start_date": "2026-09-01T00:00:00Z",
        "offer_status_enum": "ACCEPTED"
      },
      "is_confidential": false,
      "target_hire_date": "2026-09-01T00:00:00Z",
      "target_start_date": "2026-10-01T00:00:00Z",
      "employment_type_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "compensation_period": "yearly",
      "filled_by_application": {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "candidate": {
          "last_name": "Doe",
          "first_name": "Jane"
        }
      },
      "max_compensation_amount": "120000.0000",
      "min_compensation_amount": "80000.0000",
      "filled_by_application_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "compensation_currency_iso_code": "USD",
      "created_by_hris_organization_user_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "updated_by_hris_organization_user_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
    }
  ],
  "has_more": false,
  "next_cursor": "eyJpZCI6IjEyMzQifQ==",
  "total_count": 42
}
```

**SDK Code**

```python
import requests

url = "https://api.letsdeel.com/rest/ats/openings"

querystring = {"cursor":"eyJpZCI6IjEyMzQifQ==","job_ids":"[\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"]","limit":"50","location_ids":"[\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"]","status":"[\"OPEN\"]","tag_ids":"[\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"]","tag_ids_operator":"ANY","team_ids":"[\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"]"}

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript
const url = 'https://api.letsdeel.com/rest/ats/openings?cursor=eyJpZCI6IjEyMzQifQ%3D%3D&job_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&limit=50&location_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&status=%5B%22OPEN%22%5D&tag_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&tag_ids_operator=ANY&team_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.letsdeel.com/rest/ats/openings?cursor=eyJpZCI6IjEyMzQifQ%3D%3D&job_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&limit=50&location_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&status=%5B%22OPEN%22%5D&tag_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&tag_ids_operator=ANY&team_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.letsdeel.com/rest/ats/openings?cursor=eyJpZCI6IjEyMzQifQ%3D%3D&job_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&limit=50&location_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&status=%5B%22OPEN%22%5D&tag_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&tag_ids_operator=ANY&team_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.letsdeel.com/rest/ats/openings?cursor=eyJpZCI6IjEyMzQifQ%3D%3D&job_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&limit=50&location_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&status=%5B%22OPEN%22%5D&tag_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&tag_ids_operator=ANY&team_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.letsdeel.com/rest/ats/openings?cursor=eyJpZCI6IjEyMzQifQ%3D%3D&job_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&limit=50&location_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&status=%5B%22OPEN%22%5D&tag_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&tag_ids_operator=ANY&team_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.letsdeel.com/rest/ats/openings?cursor=eyJpZCI6IjEyMzQifQ%3D%3D&job_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&limit=50&location_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&status=%5B%22OPEN%22%5D&tag_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&tag_ids_operator=ANY&team_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.letsdeel.com/rest/ats/openings?cursor=eyJpZCI6IjEyMzQifQ%3D%3D&job_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&limit=50&location_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&status=%5B%22OPEN%22%5D&tag_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D&tag_ids_operator=ANY&team_ids=%5B%22f47ac10b-58cc-4372-a567-0e02b2c3d479%22%5D")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```