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

# Jobs

> Search the open jobs, publish your company's jobs, and show a pilot the jobs that fit best.

Jobs work in three ways. Any partner with `jobs.read` searches the open listings. A company with `jobs.write` publishes its own. A pilot app with a grant that holds `jobs.match` asks which open jobs fit that pilot.

## Search the open jobs

```bash theme={null}
curl "https://{api-host}/v1/partner/jobs?q=citation&position_type=first_officer&page=1&page_size=20" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```json theme={null}
{
  "items": [
    {
      "id": "6f1c2a9e-3b7d-4c51-9e2a-0d4b8f6a1c33",
      "title": "First Officer, Citation Latitude",
      "company": { "id": "9a7e2c10-5b3d-4f6a-8c21-7d0e4b6f1a52", "name": "Example Air", "logo_url": null },
      "position_type": "first_officer",
      "base_airport_code": "KTEB",
      "min_total_hours": 1500,
      "required_licenses": ["ATP"],
      "posted_at": "2026-11-05T14:00:00Z",
      "url": "https://mypilotindex.com/jobs/6f1c2a9e-3b7d-4c51-9e2a-0d4b8f6a1c33?src=share"
    }
  ],
  "page": 1,
  "page_size": 20,
  "has_more": false
}
```

The list holds active, unexpired listings, featured ones first, then the newest. `page_size` goes up to 50. `GET /v1/partner/jobs/{job_id}` reads one listing; a listing that is not active answers `404 not_found`.

## Publish a job

MyPilotIndex binds your partner to your company, and the job is published in that company's name. Without the binding the answer is `403 forbidden` with reason `partner_not_bound`.

```bash theme={null}
curl -X POST https://{api-host}/v1/partner/jobs \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "client_ref": "req-2291",
    "title": "First Officer, Citation Latitude",
    "position_type": "first_officer",
    "base_airport_code": "KTEB",
    "min_total_hours": 1500,
    "min_pic_hours": 500,
    "required_licenses": ["ATP"],
    "application_url": "https://careers.example.com/2291",
    "status": "active"
  }'
```

```json theme={null}
{ "job_id": "6f1c2a9e-3b7d-4c51-9e2a-0d4b8f6a1c33", "replayed": false }
```

`title` and `position_type` are required. `status` is `active`, which goes live at once, or `draft`, which nobody reads until a change makes it active. The [API reference](https://developers.mypilotindex.com/api-reference/introduction.md) lists every field; a member outside that list, such as `company_id` or `featured`, answers `400 invalid_request`.

`client_ref` works as it does for [publishing](https://developers.mypilotindex.com/publishing.md#retrying-safely): a retry with the same body answers `200` with `replayed: true` and publishes nothing. A partner publishes at most 50 jobs in 24 hours; past that the answer is `429 rate_limited` with reason `publication_throttled` and `Retry-After`.

## Change or close a job

`PATCH /v1/partner/jobs/{job_id}` changes the members you send and answers the job. `POST /v1/partner/jobs/{job_id}/close` archives it, and closing a closed job answers `200`.

You change only the jobs you created, for the company you are bound to. Anything else answers `404 not_found`, exactly like a job that does not exist.

Moving a closed job back to `active` reopens it for 30 more days, unless you send your own `expires_at`.

## Show a pilot the jobs that fit

```bash theme={null}
curl "https://{api-host}/v1/partner/grants/{grant_id}/job-matches?limit=10" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```json theme={null}
{
  "items": [
    {
      "id": "6f1c2a9e-3b7d-4c51-9e2a-0d4b8f6a1c33",
      "title": "First Officer, Citation Latitude",
      "match": {
        "overall": 86,
        "matchLabel": "good_match",
        "engine_version": "jobmatch.web.1",
        "detail": "plan_required"
      }
    }
  ]
}
```

The answer draws from the newest 50 active listings and orders them by match, highest first. `limit` goes up to 20.

The match is the one the pilot sees on MyPilotIndex, under the pilot's own plan. A free pilot's match carries `overall`, `matchLabel` and `detail: "plan_required"`. A paying pilot's replaces `detail` with `breakdown` and `missingRequirements`. `match` is null for a job the engine does not score, such as one for mechanics, and those jobs come last.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.