Make your first request
Check your Ur Next Door API key with GET /me, publish your first post, open it on the site, and read your remaining daily quota. About five minutes.
This page takes about five minutes. You need a key with the content scope stored in UND_API_KEY (see Create an API key).
The examples come in four languages. Pick yours once and every example on the site follows. JavaScript needs Node.js 20 or newer (save the code as a .mjs file); Python needs the requests package (pip install requests); PHP needs the curl extension.
Step 1: Check that the key is set
echo "${UND_API_KEY:0:12}..."You should see und_sk_ and five more characters. If you see only ..., the variable is empty in this terminal: set it again, or open a new terminal if you saved it in your profile.
Step 2: Ask who you are
GET /api/v1/me confirms the key works and shows your plan and the key's scopes.
curl "https://urnextdoor.com/api/v1/me" \
-H "Authorization: Bearer $UND_API_KEY"const res = await fetch("https://urnextdoor.com/api/v1/me", {
headers: {
Authorization: `Bearer ${process.env.UND_API_KEY}`,
},
});
console.log(res.status, await res.json());import os
import requests
api_key = os.environ["UND_API_KEY"]
response = requests.get(
"https://urnextdoor.com/api/v1/me",
headers={
"Authorization": f"Bearer {api_key}",
},
timeout=30,
)
print(response.status_code, response.json())<?php
$apiKey = getenv('UND_API_KEY');
$ch = curl_init('https://urnextdoor.com/api/v1/me');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
echo $status, PHP_EOL, $body, PHP_EOL;Sample response: 200 OK
{
"ok": true,
"user": {
"id": 7,
"username": "aarav",
"display_name": "Aarav",
"plan": "free",
"profile_url": "https://urnextdoor.com/users/aarav"
},
"key": {
"id": 3,
"name": "Claude Code",
"prefix": "und_sk_7Hq2x",
"scopes": [
"content",
"media",
"schedule",
"read"
],
"created_at": "2026-10-15T09:00:00Z",
"expires_at": "2027-01-13T09:00:00Z"
},
"request_id": "9f8e7d6c5b4a3921"
}If scopes does not include content, create a key that does before step 3.
Step 3: Publish a post
POST /api/v1/posts needs a title and an HTML body. The Idempotency-Key header makes it safe to retry: if you send the same request again with the same key, you get the first answer back instead of a second post.
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"
]
}'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());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
$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
{
"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"
}The post is live. web_url is its public address.
Note
This publishes for real, under your name. To try things out without publishing, add "scheduled_at" a few days ahead, check the result, then cancel it (see Manage scheduled content).
Step 4: Open it
Open the web_url from the response in a browser. You will see the post exactly as if you had written it on the website.
Step 5: See your remaining quota
Each create uses one unit of that action's daily quota. GET /api/v1/usage shows what is left today and when it resets (00:00 UTC):
curl "https://urnextdoor.com/api/v1/usage" \
-H "Authorization: Bearer $UND_API_KEY"const res = await fetch("https://urnextdoor.com/api/v1/usage", {
headers: {
Authorization: `Bearer ${process.env.UND_API_KEY}`,
},
});
console.log(res.status, await res.json());import os
import requests
api_key = os.environ["UND_API_KEY"]
response = requests.get(
"https://urnextdoor.com/api/v1/usage",
headers={
"Authorization": f"Bearer {api_key}",
},
timeout=30,
)
print(response.status_code, response.json())<?php
$apiKey = getenv('UND_API_KEY');
$ch = curl_init('https://urnextdoor.com/api/v1/usage');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
echo $status, PHP_EOL, $body, PHP_EOL;Sample response: 200 OK
{
"ok": true,
"plan": "free",
"day": "2026-10-15",
"resets_at": "2026-10-16T00:00:00Z",
"quotas": [
{
"action": "post",
"limit": 20,
"used": 3,
"remaining": 17
},
{
"action": "question",
"limit": 20,
"used": 0,
"remaining": 20
},
{
"action": "media",
"limit": 50,
"used": 2,
"remaining": 48
}
],
"request_id": "9f8e7d6c5b4a3921"
}If something went wrong
| You got | Likely cause | Fix |
|---|---|---|
401 missing_api_key | UND_API_KEY is empty in this process | Set it again, then rerun |
401 invalid_api_key | The key is mistyped, revoked or expired | Copy it again or create a new key |
403 insufficient_scope | The key lacks content | Create a key with content |
415 unsupported_media_type | Missing Content-Type: application/json | Add the header |
400 invalid_json | The body is not a JSON object | Check quotes and commas in the body |
422 validation_failed | A field is missing or wrong | Read errors, fix those fields |
421 wrong_host | You called a community subdomain | Use https://urnextdoor.com/api/v1 |
The full list is on Errors.
Next steps
- Create a post with tags, images and a community.
- Schedule content for later.
- Let an AI agent do it: Claude Code or Codex CLI.
Last updated