# Bookings, reviews and job applications

> Browse services and jobs, book and review services, move your bookings along, apply to jobs, and run the hiring pipeline for jobs you posted.

Source: https://docs.urnextdoor.com/guides/marketplace-and-jobs/

[Listing a service](https://docs.urnextdoor.com/guides/create-service.md) and [posting a job](https://docs.urnextdoor.com/guides/create-job.md) have their own guides. This one is what happens next.

**Scopes:** `browse` for reading, `marketplace` for the rest · **Quotas:** `booking` (bookings and reviews), `apply`; moving a booking or an application along is not counted

## Browse

`GET /api/v1/services` (filter by `category`, `q`, `min`, `max`, `sort`) and `GET /api/v1/jobs` (filter by `type`, `mode`, `experience`, `location`, `salary_min`), then one by its slug or id. Payment stays on the website.

## Bookings

| Step | Who | Endpoint |
| --- | --- | --- |
| Book | buyer | `POST /api/v1/services/{id}/bookings` |
| Accept or decline | provider | `POST /api/v1/bookings/{id}/accept`, `/decline` |
| Start work, deliver | provider | `POST /api/v1/bookings/{id}/progress`, `/deliver` |
| Complete | buyer or provider | `POST /api/v1/bookings/{id}/complete` |
| Cancel | buyer or provider | `POST /api/v1/bookings/{id}/cancel` |
| List | either | `GET /api/v1/bookings?tab=received` (or `placed`) |

**cURL**

```bash
curl -X POST "https://urnextdoor.com/api/v1/services/41/bookings" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "package_id": 7,
  "quantity": 1,
  "requirements": "A balcony of 3 by 2 metres."
}'
```

**JavaScript**

```js
const res = await fetch("https://urnextdoor.com/api/v1/services/41/bookings", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    package_id: 7,
    quantity: 1,
    requirements: "A balcony of 3 by 2 metres.",
  }),
});
console.log(res.status, await res.json());
```

**Python**

```python
import os
import uuid

import requests

api_key = os.environ["UND_API_KEY"]

response = requests.post(
    "https://urnextdoor.com/api/v1/services/41/bookings",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "package_id": 7,
        "quantity": 1,
        "requirements": "A balcony of 3 by 2 metres.",
    },
    timeout=30,
)
print(response.status_code, response.json())
```

**PHP**

```php
<?php
$apiKey = getenv('UND_API_KEY');

$payload = [
    'package_id' => 7,
    'quantity' => 1,
    'requirements' => 'A balcony of 3 by 2 metres.',
];

$ch = curl_init('https://urnextdoor.com/api/v1/services/41/bookings');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
        'Idempotency-Key: ' . bin2hex(random_bytes(16)),
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

echo $status, PHP_EOL, $body, PHP_EOL;
```

Through a key, only the provider and the buyer themselves act on a booking: a community moderator who could on the website answers `403 not_your_content`. Marking a booking paid stays on the website.

## Reviews

After a completed booking, the buyer reviews the service (`POST /api/v1/services/{id}/reviews`, 1 to 5 stars) and can edit it (`PUT /api/v1/reviews/{id}`). The provider replies with `POST /api/v1/reviews/{id}/reply`; the `reply` field is required, and an empty one removes the reply.

## Applying to jobs

`POST /api/v1/jobs/{id}/applications` with an optional `cover_note`. You need a CV first: without one, the answer is `422 cv_missing`. `GET /api/v1/applications?tab=applied` lists yours; `POST /api/v1/applications/{id}/withdraw` takes one back.

## Hiring for your job

`GET /api/v1/jobs/{id}/applications` lists the applicants to your job. Move each with `POST /api/v1/applications/{id}/review`, `/shortlist`, `/interview`, `/offer`, `/hire` or `/reject` (with an optional `recruiter_note`). The applicant is told each time. Only the member who posted the job can do this through a key.

## Next steps

- [Edit your content](https://docs.urnextdoor.com/guides/edit-content.md), including your services and jobs.
- [Messages](https://docs.urnextdoor.com/guides/messages.md) to talk to a buyer or applicant.
- [API reference: Marketplace](https://docs.urnextdoor.com/reference/marketplace.md).
