# Use the API with Zapier

> Publish to Ur Next Door from a Zap with Webhooks by Zapier: header setup for your API key, a JSON body, and a spreadsheet row to scheduled post example.

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

[Zapier](https://zapier.com) connects apps with Zaps. There is no dedicated Ur Next Door app in Zapier; use the built-in **Webhooks by Zapier** action, which sends any HTTP request. Zapier lists Webhooks by Zapier as a premium app, so check that your Zapier plan includes it.

## Step 1: Create a key for Zapier

Create a key named `Zapier` with only the scopes the Zap needs, usually just `content`. See [Create an API key](https://docs.urnextdoor.com/getting-started/create-api-key.md).

## Step 2: Add the action

1. In your Zap, add an action step and choose **Webhooks by Zapier**.
2. Choose the event **Custom Request**.
3. Fill in:

| Field | Value |
| --- | --- |
| Method | `POST` |
| URL | `https://urnextdoor.com/api/v1/posts` |
| Data | The JSON body (below) |
| Headers | `Authorization` = `Bearer und_sk_...`; `Content-Type` = `application/json`; `Idempotency-Key` = a value unique per item, such as the trigger's row or record id |

Data:

```json
{
  "title": "TITLE FROM THE TRIGGER",
  "body": "<p>BODY FROM THE TRIGGER</p>",
  "scheduled_at": "TIME FROM THE TRIGGER, IN UTC ENDING IN Z"
}
```

Insert trigger fields where the capitals are. Text that contains double quotes breaks raw JSON; use a **Formatter** step to escape it, or keep those fields free of quotes.

4. Test the step. A `201` answer with a `web_url` means it worked.

The request Zapier sends is equivalent to:

**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"
  ],
  "scheduled_at": "2026-10-20T09:30:00Z"
}'
```

**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"],
    scheduled_at: "2026-10-20T09:30:00Z",
  }),
});
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"],
        "scheduled_at": "2026-10-20T09:30:00Z",
    },
    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'],
    'scheduled_at' => '2026-10-20T09:30:00Z',
];

$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",
  "status": "scheduled",
  "scheduled_at": "2026-10-20T09:30:00Z",
  "item": {
    "id": 41,
    "type": "post",
    "slug": "five-easy-ways-to-save-water-at-home"
  },
  "request_id": "9f8e7d6c5b4a3921"
}
```

## Example: publish from a spreadsheet

1. **Trigger:** Google Sheets, *New Spreadsheet Row*, on a sheet with the columns `title`, `body_html`, `publish_at_utc` and `id`.
2. **Action:** Webhooks by Zapier, *Custom Request*, as above, with `scheduled_at` mapped to `publish_at_utc` and `Idempotency-Key` mapped to `id`.
3. Turn the Zap on. Each new row becomes a scheduled post on Ur Next Door.

Times in the sheet must be UTC ending in `Z`, between 5 minutes and 180 days ahead. See [Schedule content](https://docs.urnextdoor.com/guides/schedule-content.md).

## Keep the key safe in Zapier

The key sits in the step's headers. Anyone who can edit the Zap can read it, so do not share the Zap with people who should not post as you. Use a key with only the `content` scope and a short expiry, and [revoke it](https://docs.urnextdoor.com/security.md) if the Zap is ever shared by mistake.

## Next steps

- [n8n](https://docs.urnextdoor.com/integrations/n8n.md) for self-hosted workflows.
- [Schedule content](https://docs.urnextdoor.com/guides/schedule-content.md).
- [Rate limits and daily quotas](https://docs.urnextdoor.com/limits.md).
