# Use the API with cURL

> Call the Ur Next Door API from the command line with cURL: a reusable shell helper, JSON bodies from files, reading headers, jq, and Windows notes.

Source: https://docs.urnextdoor.com/integrations/curl/

cURL is installed on macOS, Linux and Windows 10 or later. Every example in these docs has a cURL tab; this page collects the habits that make it pleasant.

## Set the key once

```bash
read -rs UND_API_KEY && export UND_API_KEY
```

Every command below uses `$UND_API_KEY`, so the key never appears in your history.

## A small helper

Put this in your shell profile to stop repeating the base URL and headers:

```bash
und() {
  local method="$1" path="$2"
  shift 2
  curl -sS -X "$method" "https://urnextdoor.com/api/v1$path" \
    -H "Authorization: Bearer $UND_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $(uuidgen)" \
    "$@"
}
```

Then:

```bash
und GET /me
und GET /usage
und POST /posts -d @post.json
und GET "/geo?level=states&country=IN"
```

The API ignores `Idempotency-Key` on `GET`. For a retry that must reuse the same key, call `curl` directly with a fixed value instead of the helper.

## Keep bodies in files

Quoting JSON on the command line is error prone, especially HTML with quotes. Write the body to a file and send it with `-d @file`:

**post.json**

```json
{
  "title": "Five easy ways to save water at home",
  "body": "<p>Small habits add up.</p><ul><li>Fix dripping taps the same week.</li></ul>",
  "tags": ["water", "home"]
}
```

```bash
und POST /posts -d @post.json
```

For large bodies, such as a base64 image, use `--data-binary @upload.json` so cURL sends the file exactly as it is. See [Upload images](https://docs.urnextdoor.com/guides/upload-images.md).

## The full request, without the helper

**cURL**

```bash
curl -X POST "https://urnextdoor.com/api/v1/posts" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "title": "Five easy ways to save water at home",
  "body": "<p>Small habits add up. These five saved our building a lot of water this summer.</p><ul><li>Fix dripping taps the same week.</li><li>Run the washing machine only when it is full.</li></ul>",
  "tags": [
    "water",
    "home"
  ]
}'
```

**JavaScript**

```js
const res = await fetch("https://urnextdoor.com/api/v1/posts", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    title: "Five easy ways to save water at home",
    body: "<p>Small habits add up. These five saved our building a lot of water this summer.</p><ul><li>Fix dripping taps the same week.</li><li>Run the washing machine only when it is full.</li></ul>",
    tags: ["water", "home"],
  }),
});
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/posts",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "title": "Five easy ways to save water at home",
        "body": "<p>Small habits add up. These five saved our building a lot of water this summer.</p><ul><li>Fix dripping taps the same week.</li><li>Run the washing machine only when it is full.</li></ul>",
        "tags": ["water", "home"],
    },
    timeout=30,
)
print(response.status_code, response.json())
```

**PHP**

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

$payload = [
    'title' => 'Five easy ways to save water at home',
    'body' => '<p>Small habits add up. These five saved our building a lot of water this summer.</p><ul><li>Fix dripping taps the same week.</li><li>Run the washing machine only when it is full.</li></ul>',
    'tags' => ['water', 'home'],
];

$ch = curl_init('https://urnextdoor.com/api/v1/posts');
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;
```

Sample response: `201 Created`

```json
{
  "ok": true,
  "id": 41,
  "slug": "five-easy-ways-to-save-water-at-home",
  "url": "/posts/five-easy-ways-to-save-water-at-home",
  "web_url": "https://urnextdoor.com/posts/five-easy-ways-to-save-water-at-home",
  "item": {
    "id": 41,
    "type": "post",
    "slug": "five-easy-ways-to-save-water-at-home"
  },
  "request_id": "9f8e7d6c5b4a3921"
}
```

## Read headers and pick fields

```bash
# Show response headers too (quota, request id)
curl -sS -D - "https://urnextdoor.com/api/v1/usage" -H "Authorization: Bearer $UND_API_KEY"

# With jq installed: print only the link of a new post
und POST /posts -d @post.json | jq -r '.web_url'
```

`-D -` prints headers such as `X-Request-Id` and, on creates, `X-RateLimit-Remaining`.

## Windows

In PowerShell, call `curl.exe` (plain `curl` may be an alias for a different command in older Windows PowerShell), and keep bodies in files:

```powershell
curl.exe -sS -X POST "https://urnextdoor.com/api/v1/posts" `
  -H "Authorization: Bearer $env:UND_API_KEY" `
  -H "Content-Type: application/json" `
  -H "Idempotency-Key: $([guid]::NewGuid())" `
  --data-binary "@post.json"
```

`uuidgen` is not available on Windows; `[guid]::NewGuid()` does the same job.

## Next steps

- [Postman](https://docs.urnextdoor.com/integrations/postman.md) if you prefer a visual client.
- [Idempotency](https://docs.urnextdoor.com/idempotency.md).
- [API reference](https://docs.urnextdoor.com/reference.md).
