Content endpoints

Create posts, questions, polls, MCQs, communities, Marketplace services and jobs, now or at a scheduled time.

View as Markdown

All paths are relative to https://urnextdoor.com/api/v1. See API reference for the envelope and headers every endpoint shares.

EndpointWhat it doesScopeDaily quota
POST /postsCreate a postcontentpost
POST /questionsAsk a questioncontentquestion
POST /pollsCreate a pollcontentpoll
POST /mcqsCreate an MCQcontentmcq
POST /communitiesCreate a communitycontentcommunity
POST /servicesList a servicecontentservice
POST /jobsPost a jobcontentjob

Create a post

POST https://urnextdoor.com/api/v1/posts

Publishes a post now, or schedules it when scheduled_at is set. title and body (HTML) are required. Send an Idempotency-Key so a retry never posts twice. Counts against the post quota.

  • Auth: your API key (Bearer or X-API-Key)
  • Scope: content
  • Daily quota: counts as post (see limits)
  • Idempotency-Key: supported (see Idempotency)
  • operationId: createPost

Request body

Send Content-Type: application/json.

FieldTypeRequiredDescription
titlestringYesThe post title (plain text).
bodystringYesThe post body as HTML. See the Formatting guide for allowed tags.
tagsarray of stringNoTopic tags, without the leading #. Example: ["water", "home"].
community_idintegerNoPost inside this community. Use an id from GET /communities/postable. You must be an editor (or above) of it.
communitystringNoAlternative to community_id: the community slug. It is resolved to its id.
featured_imagestringNoA /storage/... path returned by POST /media (data.url), or any https:// image URL (linked, not copied).
galleryarray of stringNoExtra images. Each is a /storage/... path from POST /media or an https:// image URL. Up to 12 items.
scheduled_atstring (date-time)NoPublish later instead of now. ISO 8601 with an offset or Z, at least 5 minutes and at most 180 days ahead. Stored in UTC.

Example

cURL
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
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
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
$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"
}

Responses

StatusMeaningCodes
201 CreatedCreated. Published now, or scheduled when scheduled_at was sent.
400 Bad RequestThe body is not a JSON object, or the Idempotency-Key header is malformed.invalid_json, invalid_idempotency_key
401 UnauthorizedNo key, or the key is unknown, malformed, revoked or expired, or the member is not active.missing_api_key, invalid_api_key
403 ForbiddenThe key lacks the scope, or the member may not do this.insufficient_scope, forbidden
404 Not FoundUnknown route or item, or the item is not yours.not_found
409 ConflictConflicts with the current state, or the same Idempotency-Key is still being processed.conflict, idempotency_in_progress
413 Payload Too LargeThe body is over the limit, or the image is over 8 MB.payload_too_large
415 Unsupported Media TypeWrong Content-Type, or a file type that is not allowed.unsupported_media_type
421 Misdirected RequestCalled on a community subdomain. Use https://urnextdoor.com.wrong_host
422 Unprocessable ContentField errors, or an Idempotency-Key reused with a different body.validation_failed, idempotency_key_reused
429 Too Many RequestsOver 60 requests a minute from this member (or too many failed key checks from one address), or today's quota for this action is used up.rate_limited, quota_exceeded
500 Internal Server ErrorOur fault. Safe to retry with the same Idempotency-Key.server_error
503 Service UnavailableThe API is switched off.api_disabled

Ask a question

POST https://urnextdoor.com/api/v1/questions

Publishes a question now, or schedules it when scheduled_at is set. Only title is required; body (HTML) adds details. Counts against the question quota.

  • Auth: your API key (Bearer or X-API-Key)
  • Scope: content
  • Daily quota: counts as question (see limits)
  • Idempotency-Key: supported (see Idempotency)
  • operationId: createQuestion

Request body

Send Content-Type: application/json.

FieldTypeRequiredDescription
titlestringYesThe question itself (plain text).
bodystringNoOptional details as HTML.
tagsarray of stringNoTopic tags, without the leading #. Example: ["water", "home"].
community_idintegerNoPost inside this community. Use an id from GET /communities/postable. You must be an editor (or above) of it.
communitystringNoAlternative to community_id: the community slug. It is resolved to its id.
featured_imagestringNoA /storage/... path returned by POST /media (data.url), or any https:// image URL (linked, not copied).
galleryarray of stringNoExtra images. Each is a /storage/... path from POST /media or an https:// image URL. Up to 12 items.
scheduled_atstring (date-time)NoPublish later instead of now. ISO 8601 with an offset or Z, at least 5 minutes and at most 180 days ahead. Stored in UTC.

Example

cURL
curl -X POST "https://urnextdoor.com/api/v1/questions" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "title": "Which plants survive a north facing balcony?",
  "body": "<p>We get about two hours of direct sun. What has worked for you?</p>",
  "tags": [
    "gardening"
  ]
}'
JavaScript
const res = await fetch("https://urnextdoor.com/api/v1/questions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    title: "Which plants survive a north facing balcony?",
    body: "<p>We get about two hours of direct sun. What has worked for you?</p>",
    tags: ["gardening"],
  }),
});
console.log(res.status, await res.json());
Python
import os
import uuid

import requests

api_key = os.environ["UND_API_KEY"]

response = requests.post(
    "https://urnextdoor.com/api/v1/questions",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "title": "Which plants survive a north facing balcony?",
        "body": "<p>We get about two hours of direct sun. What has worked for you?</p>",
        "tags": ["gardening"],
    },
    timeout=30,
)
print(response.status_code, response.json())
PHP
<?php
$apiKey = getenv('UND_API_KEY');

$payload = [
    'title' => 'Which plants survive a north facing balcony?',
    'body' => '<p>We get about two hours of direct sun. What has worked for you?</p>',
    'tags' => ['gardening'],
];

$ch = curl_init('https://urnextdoor.com/api/v1/questions');
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": 52,
  "slug": "which-plants-survive-a-north-facing-balcony",
  "url": "/questions/which-plants-survive-a-north-facing-balcony",
  "web_url": "https://urnextdoor.com/questions/which-plants-survive-a-north-facing-balcony",
  "item": {
    "id": 52,
    "type": "question",
    "slug": "which-plants-survive-a-north-facing-balcony"
  },
  "request_id": "9f8e7d6c5b4a3921"
}

Responses

StatusMeaningCodes
201 CreatedCreated. Published now, or scheduled when scheduled_at was sent.
400 Bad RequestThe body is not a JSON object, or the Idempotency-Key header is malformed.invalid_json, invalid_idempotency_key
401 UnauthorizedNo key, or the key is unknown, malformed, revoked or expired, or the member is not active.missing_api_key, invalid_api_key
403 ForbiddenThe key lacks the scope, or the member may not do this.insufficient_scope, forbidden
404 Not FoundUnknown route or item, or the item is not yours.not_found
409 ConflictConflicts with the current state, or the same Idempotency-Key is still being processed.conflict, idempotency_in_progress
413 Payload Too LargeThe body is over the limit, or the image is over 8 MB.payload_too_large
415 Unsupported Media TypeWrong Content-Type, or a file type that is not allowed.unsupported_media_type
421 Misdirected RequestCalled on a community subdomain. Use https://urnextdoor.com.wrong_host
422 Unprocessable ContentField errors, or an Idempotency-Key reused with a different body.validation_failed, idempotency_key_reused
429 Too Many RequestsOver 60 requests a minute from this member (or too many failed key checks from one address), or today's quota for this action is used up.rate_limited, quota_exceeded
500 Internal Server ErrorOur fault. Safe to retry with the same Idempotency-Key.server_error
503 Service UnavailableThe API is switched off.api_disabled

Create a poll

POST https://urnextdoor.com/api/v1/polls

Publishes a poll now, or schedules it. title and options (2 to 5 unique strings) are required. Counts against the poll quota.

  • Auth: your API key (Bearer or X-API-Key)
  • Scope: content
  • Daily quota: counts as poll (see limits)
  • Idempotency-Key: supported (see Idempotency)
  • operationId: createPoll

Request body

Send Content-Type: application/json.

FieldTypeRequiredDescription
titlestringYesThe poll question (plain text).
optionsarray of stringYesThe answers people vote on: 2 to 5 unique strings. 2 to 5 items. Items must be unique.
bodystringNoOptional context as HTML.
tagsarray of stringNoTopic tags, without the leading #. Example: ["water", "home"].
community_idintegerNoPost inside this community. Use an id from GET /communities/postable. You must be an editor (or above) of it.
communitystringNoAlternative to community_id: the community slug. It is resolved to its id.
featured_imagestringNoA /storage/... path returned by POST /media (data.url), or any https:// image URL (linked, not copied).
galleryarray of stringNoExtra images. Each is a /storage/... path from POST /media or an https:// image URL. Up to 12 items.
scheduled_atstring (date-time)NoPublish later instead of now. ISO 8601 with an offset or Z, at least 5 minutes and at most 180 days ahead. Stored in UTC.

Example

cURL
curl -X POST "https://urnextdoor.com/api/v1/polls" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "title": "When should the weekend cleanup start?",
  "options": [
    "7 am",
    "8 am",
    "9 am"
  ],
  "tags": [
    "neighbourhood"
  ]
}'
JavaScript
const res = await fetch("https://urnextdoor.com/api/v1/polls", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    title: "When should the weekend cleanup start?",
    options: ["7 am", "8 am", "9 am"],
    tags: ["neighbourhood"],
  }),
});
console.log(res.status, await res.json());
Python
import os
import uuid

import requests

api_key = os.environ["UND_API_KEY"]

response = requests.post(
    "https://urnextdoor.com/api/v1/polls",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "title": "When should the weekend cleanup start?",
        "options": ["7 am", "8 am", "9 am"],
        "tags": ["neighbourhood"],
    },
    timeout=30,
)
print(response.status_code, response.json())
PHP
<?php
$apiKey = getenv('UND_API_KEY');

$payload = [
    'title' => 'When should the weekend cleanup start?',
    'options' => ['7 am', '8 am', '9 am'],
    'tags' => ['neighbourhood'],
];

$ch = curl_init('https://urnextdoor.com/api/v1/polls');
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": 18,
  "slug": "when-should-the-weekend-cleanup-start",
  "url": "/polls/when-should-the-weekend-cleanup-start",
  "web_url": "https://urnextdoor.com/polls/when-should-the-weekend-cleanup-start",
  "item": {
    "id": 18,
    "type": "poll",
    "slug": "when-should-the-weekend-cleanup-start"
  },
  "request_id": "9f8e7d6c5b4a3921"
}

Responses

StatusMeaningCodes
201 CreatedCreated. Published now, or scheduled when scheduled_at was sent.
400 Bad RequestThe body is not a JSON object, or the Idempotency-Key header is malformed.invalid_json, invalid_idempotency_key
401 UnauthorizedNo key, or the key is unknown, malformed, revoked or expired, or the member is not active.missing_api_key, invalid_api_key
403 ForbiddenThe key lacks the scope, or the member may not do this.insufficient_scope, forbidden
404 Not FoundUnknown route or item, or the item is not yours.not_found
409 ConflictConflicts with the current state, or the same Idempotency-Key is still being processed.conflict, idempotency_in_progress
413 Payload Too LargeThe body is over the limit, or the image is over 8 MB.payload_too_large
415 Unsupported Media TypeWrong Content-Type, or a file type that is not allowed.unsupported_media_type
421 Misdirected RequestCalled on a community subdomain. Use https://urnextdoor.com.wrong_host
422 Unprocessable ContentField errors, or an Idempotency-Key reused with a different body.validation_failed, idempotency_key_reused
429 Too Many RequestsOver 60 requests a minute from this member (or too many failed key checks from one address), or today's quota for this action is used up.rate_limited, quota_exceeded
500 Internal Server ErrorOur fault. Safe to retry with the same Idempotency-Key.server_error
503 Service UnavailableThe API is switched off.api_disabled

Create an MCQ

POST https://urnextdoor.com/api/v1/mcqs

Publishes a multiple choice quiz question now, or schedules it. title, options (2 to 5) and correct_option_index (0-based) are required. Counts against the mcq quota.

  • Auth: your API key (Bearer or X-API-Key)
  • Scope: content
  • Daily quota: counts as mcq (see limits)
  • Idempotency-Key: supported (see Idempotency)
  • operationId: createMcq

Request body

Send Content-Type: application/json.

FieldTypeRequiredDescription
titlestringYesThe quiz question (plain text).
optionsarray of stringYesThe choices: 2 to 5 unique strings. 2 to 5 items. Items must be unique.
correct_option_indexintegerYesThe 0-based position of the correct choice in options. From 0 to 4.
bodystringNoOptional context or explanation as HTML.
tagsarray of stringNoTopic tags, without the leading #. Example: ["water", "home"].
community_idintegerNoPost inside this community. Use an id from GET /communities/postable. You must be an editor (or above) of it.
communitystringNoAlternative to community_id: the community slug. It is resolved to its id.
featured_imagestringNoA /storage/... path returned by POST /media (data.url), or any https:// image URL (linked, not copied).
galleryarray of stringNoExtra images. Each is a /storage/... path from POST /media or an https:// image URL. Up to 12 items.
scheduled_atstring (date-time)NoPublish later instead of now. ISO 8601 with an offset or Z, at least 5 minutes and at most 180 days ahead. Stored in UTC.

Example

cURL
curl -X POST "https://urnextdoor.com/api/v1/mcqs" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "title": "Which planet has the shortest year?",
  "options": [
    "Venus",
    "Mercury",
    "Mars",
    "Earth"
  ],
  "correct_option_index": 1,
  "tags": [
    "science"
  ]
}'
JavaScript
const res = await fetch("https://urnextdoor.com/api/v1/mcqs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    title: "Which planet has the shortest year?",
    options: ["Venus", "Mercury", "Mars", "Earth"],
    correct_option_index: 1,
    tags: ["science"],
  }),
});
console.log(res.status, await res.json());
Python
import os
import uuid

import requests

api_key = os.environ["UND_API_KEY"]

response = requests.post(
    "https://urnextdoor.com/api/v1/mcqs",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "title": "Which planet has the shortest year?",
        "options": ["Venus", "Mercury", "Mars", "Earth"],
        "correct_option_index": 1,
        "tags": ["science"],
    },
    timeout=30,
)
print(response.status_code, response.json())
PHP
<?php
$apiKey = getenv('UND_API_KEY');

$payload = [
    'title' => 'Which planet has the shortest year?',
    'options' => ['Venus', 'Mercury', 'Mars', 'Earth'],
    'correct_option_index' => 1,
    'tags' => ['science'],
];

$ch = curl_init('https://urnextdoor.com/api/v1/mcqs');
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": 77,
  "slug": "which-planet-has-the-shortest-year",
  "url": "/mcqs/which-planet-has-the-shortest-year",
  "web_url": "https://urnextdoor.com/mcqs/which-planet-has-the-shortest-year",
  "item": {
    "id": 77,
    "type": "mcq",
    "slug": "which-planet-has-the-shortest-year"
  },
  "request_id": "9f8e7d6c5b4a3921"
}

Responses

StatusMeaningCodes
201 CreatedCreated. Published now, or scheduled when scheduled_at was sent.
400 Bad RequestThe body is not a JSON object, or the Idempotency-Key header is malformed.invalid_json, invalid_idempotency_key
401 UnauthorizedNo key, or the key is unknown, malformed, revoked or expired, or the member is not active.missing_api_key, invalid_api_key
403 ForbiddenThe key lacks the scope, or the member may not do this.insufficient_scope, forbidden
404 Not FoundUnknown route or item, or the item is not yours.not_found
409 ConflictConflicts with the current state, or the same Idempotency-Key is still being processed.conflict, idempotency_in_progress
413 Payload Too LargeThe body is over the limit, or the image is over 8 MB.payload_too_large
415 Unsupported Media TypeWrong Content-Type, or a file type that is not allowed.unsupported_media_type
421 Misdirected RequestCalled on a community subdomain. Use https://urnextdoor.com.wrong_host
422 Unprocessable ContentField errors, or an Idempotency-Key reused with a different body.validation_failed, idempotency_key_reused
429 Too Many RequestsOver 60 requests a minute from this member (or too many failed key checks from one address), or today's quota for this action is used up.rate_limited, quota_exceeded
500 Internal Server ErrorOur fault. Safe to retry with the same Idempotency-Key.server_error
503 Service UnavailableThe API is switched off.api_disabled

Create a community

POST https://urnextdoor.com/api/v1/communities

Creates a community now (201), or schedules its creation (202) when scheduled_at is set. name must be unique. A scheduled creation fails later if the name is taken by then. Counts against the community quota.

  • Auth: your API key (Bearer or X-API-Key)
  • Scope: content
  • Daily quota: counts as community (see limits)
  • Idempotency-Key: supported (see Idempotency)
  • operationId: createCommunity

Request body

Send Content-Type: application/json.

FieldTypeRequiredDescription
namestringYesThe community name. It must be unique.
descriptionstringNoWhat the community is about, as HTML.
visibilitystringNoWho can see and join it. One of: public, ask_to_join, private.
icon_urlstringNoOne of the paths returned by GET /community-icons.
scheduled_atstring (date-time)NoPublish later instead of now. ISO 8601 with an offset or Z, at least 5 minutes and at most 180 days ahead. Stored in UTC.

Example

cURL
curl -X POST "https://urnextdoor.com/api/v1/communities" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "name": "Morning Runners Pune",
  "description": "<p>Early runs, routes and race plans around Pune.</p>",
  "visibility": "public",
  "icon_url": "/avatars/community/running.png"
}'
JavaScript
const res = await fetch("https://urnextdoor.com/api/v1/communities", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    name: "Morning Runners Pune",
    description: "<p>Early runs, routes and race plans around Pune.</p>",
    visibility: "public",
    icon_url: "/avatars/community/running.png",
  }),
});
console.log(res.status, await res.json());
Python
import os
import uuid

import requests

api_key = os.environ["UND_API_KEY"]

response = requests.post(
    "https://urnextdoor.com/api/v1/communities",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "name": "Morning Runners Pune",
        "description": "<p>Early runs, routes and race plans around Pune.</p>",
        "visibility": "public",
        "icon_url": "/avatars/community/running.png",
    },
    timeout=30,
)
print(response.status_code, response.json())
PHP
<?php
$apiKey = getenv('UND_API_KEY');

$payload = [
    'name' => 'Morning Runners Pune',
    'description' => '<p>Early runs, routes and race plans around Pune.</p>',
    'visibility' => 'public',
    'icon_url' => '/avatars/community/running.png',
];

$ch = curl_init('https://urnextdoor.com/api/v1/communities');
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": 5,
  "slug": "morning-runners-pune",
  "url": "/communities/morning-runners-pune",
  "web_url": "https://urnextdoor.com/communities/morning-runners-pune",
  "item": {
    "id": 5,
    "type": "community",
    "slug": "morning-runners-pune",
    "name": "Morning Runners Pune"
  },
  "request_id": "9f8e7d6c5b4a3921"
}

Responses

StatusMeaningCodes
201 CreatedCreated now.
202 AcceptedAccepted: the community will be created at scheduled_at. id is the scheduled-creation id.
400 Bad RequestThe body is not a JSON object, or the Idempotency-Key header is malformed.invalid_json, invalid_idempotency_key
401 UnauthorizedNo key, or the key is unknown, malformed, revoked or expired, or the member is not active.missing_api_key, invalid_api_key
403 ForbiddenThe key lacks the scope, or the member may not do this.insufficient_scope, forbidden
404 Not FoundUnknown route or item, or the item is not yours.not_found
409 ConflictConflicts with the current state, or the same Idempotency-Key is still being processed.conflict, idempotency_in_progress
413 Payload Too LargeThe body is over the limit, or the image is over 8 MB.payload_too_large
415 Unsupported Media TypeWrong Content-Type, or a file type that is not allowed.unsupported_media_type
421 Misdirected RequestCalled on a community subdomain. Use https://urnextdoor.com.wrong_host
422 Unprocessable ContentField errors, or an Idempotency-Key reused with a different body.validation_failed, idempotency_key_reused
429 Too Many RequestsOver 60 requests a minute from this member (or too many failed key checks from one address), or today's quota for this action is used up.rate_limited, quota_exceeded
500 Internal Server ErrorOur fault. Safe to retry with the same Idempotency-Key.server_error
503 Service UnavailableThe API is switched off.api_disabled

List a service

POST https://urnextdoor.com/api/v1/services

Publishes a Marketplace service now, or schedules it. title, body and category_id are required, plus a location (country_code, postal_code, state_id) unless service_mode is online. Prices are in rupees.

  • Auth: your API key (Bearer or X-API-Key)
  • Scope: content
  • Daily quota: counts as service (see limits)
  • Idempotency-Key: supported (see Idempotency)
  • operationId: createService

Request body

Send Content-Type: application/json.

FieldTypeRequiredDescription
titlestringYesThe service title (plain text).
bodystringYesThe full description as HTML.
category_idintegerYesA category id from GET /service-categories.
summarystringNoA short plain text summary shown on cards. Up to 300 characters.
service_modestringNoHow you deliver. Unless it is online, a location is required. One of: online, in_person, both. Default: both.
country_codestringNoISO 3166-1 alpha-2 country, for example IN. Required unless service_mode is online.
postal_codestringNoPostal code, valid for the country. Required unless service_mode is online.
state_idintegerNoFrom GET /geo?level=states. At least a state (or a district or city) is required unless service_mode is online.
district_idintegerNoFrom GET /geo?level=districts. If you send a district, also send a city.
city_idintegerNoFrom GET /geo?level=cities.
areastringNoNeighbourhood or area, free text. Up to 120 characters.
packagesarray of objectNoUp to 3 priced packages. Up to 3 items.
packages[].namestringNoPackage name. Defaults to Basic, Standard or Premium by position. Up to 120 characters.
packages[].descriptionstringNoWhat the package includes. Up to 500 characters.
packages[].pricenumberYesPrice in Indian rupees, for example 4999. A package without a positive price is skipped.
packages[].delivery_daysintegerNoDays to deliver. Defaults to 1.
packages[].revisionsintegerNoRevisions included. -1 means unlimited.
packages[].featuresarray of stringNoShort feature lines, up to 20. Up to 20 items.
faqsarray of objectNoUp to 20 questions and answers. Up to 20 items.
faqs[].qstringYesThe question. Up to 200 characters.
faqs[].astringYesThe answer. Up to 1000 characters.
tagsarray of stringNoTopic tags, without the leading #. Example: ["water", "home"].
community_idintegerNoPost inside this community. Use an id from GET /communities/postable. You must be an editor (or above) of it.
communitystringNoAlternative to community_id: the community slug. It is resolved to its id.
featured_imagestringNoA /storage/... path returned by POST /media (data.url), or any https:// image URL (linked, not copied).
galleryarray of stringNoExtra images. Each is a /storage/... path from POST /media or an https:// image URL. Up to 12 items.
scheduled_atstring (date-time)NoPublish later instead of now. ISO 8601 with an offset or Z, at least 5 minutes and at most 180 days ahead. Stored in UTC.

Example

cURL
curl -X POST "https://urnextdoor.com/api/v1/services" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "title": "Business website in 7 days",
  "body": "<p>I build fast, mobile friendly websites for small shops and clinics.</p><ul><li>Design and build</li><li>Hosting setup</li></ul>",
  "category_id": 12,
  "summary": "A fast, mobile friendly website for your shop or clinic.",
  "service_mode": "online",
  "packages": [
    {
      "name": "Starter",
      "description": "One page site",
      "price": 4999,
      "delivery_days": 5,
      "revisions": 2,
      "features": [
        "1 page",
        "Contact form"
      ]
    },
    {
      "name": "Business",
      "description": "Up to 5 pages",
      "price": 14999,
      "delivery_days": 7,
      "revisions": -1,
      "features": [
        "5 pages",
        "Blog",
        "Basic SEO"
      ]
    }
  ],
  "faqs": [
    {
      "q": "Do you provide hosting?",
      "a": "I set it up on your account, so you own it."
    }
  ],
  "tags": [
    "web-design"
  ]
}'
JavaScript
const res = await fetch("https://urnextdoor.com/api/v1/services", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    title: "Business website in 7 days",
    body: "<p>I build fast, mobile friendly websites for small shops and clinics.</p><ul><li>Design and build</li><li>Hosting setup</li></ul>",
    category_id: 12,
    summary: "A fast, mobile friendly website for your shop or clinic.",
    service_mode: "online",
    packages: [
      {
        name: "Starter",
        description: "One page site",
        price: 4999,
        delivery_days: 5,
        revisions: 2,
        features: ["1 page", "Contact form"],
      },
      {
        name: "Business",
        description: "Up to 5 pages",
        price: 14999,
        delivery_days: 7,
        revisions: -1,
        features: ["5 pages", "Blog", "Basic SEO"],
      },
    ],
    faqs: [
      {
        q: "Do you provide hosting?",
        a: "I set it up on your account, so you own it.",
      },
    ],
    tags: ["web-design"],
  }),
});
console.log(res.status, await res.json());
Python
import os
import uuid

import requests

api_key = os.environ["UND_API_KEY"]

response = requests.post(
    "https://urnextdoor.com/api/v1/services",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "title": "Business website in 7 days",
        "body": "<p>I build fast, mobile friendly websites for small shops and clinics.</p><ul><li>Design and build</li><li>Hosting setup</li></ul>",
        "category_id": 12,
        "summary": "A fast, mobile friendly website for your shop or clinic.",
        "service_mode": "online",
        "packages": [
            {
                "name": "Starter",
                "description": "One page site",
                "price": 4999,
                "delivery_days": 5,
                "revisions": 2,
                "features": ["1 page", "Contact form"],
            },
            {
                "name": "Business",
                "description": "Up to 5 pages",
                "price": 14999,
                "delivery_days": 7,
                "revisions": -1,
                "features": ["5 pages", "Blog", "Basic SEO"],
            },
        ],
        "faqs": [
            {
                "q": "Do you provide hosting?",
                "a": "I set it up on your account, so you own it.",
            },
        ],
        "tags": ["web-design"],
    },
    timeout=30,
)
print(response.status_code, response.json())
PHP
<?php
$apiKey = getenv('UND_API_KEY');

$payload = [
    'title' => 'Business website in 7 days',
    'body' => '<p>I build fast, mobile friendly websites for small shops and clinics.</p><ul><li>Design and build</li><li>Hosting setup</li></ul>',
    'category_id' => 12,
    'summary' => 'A fast, mobile friendly website for your shop or clinic.',
    'service_mode' => 'online',
    'packages' => [
        [
            'name' => 'Starter',
            'description' => 'One page site',
            'price' => 4999,
            'delivery_days' => 5,
            'revisions' => 2,
            'features' => ['1 page', 'Contact form'],
        ],
        [
            'name' => 'Business',
            'description' => 'Up to 5 pages',
            'price' => 14999,
            'delivery_days' => 7,
            'revisions' => -1,
            'features' => ['5 pages', 'Blog', 'Basic SEO'],
        ],
    ],
    'faqs' => [
        [
            'q' => 'Do you provide hosting?',
            'a' => 'I set it up on your account, so you own it.',
        ],
    ],
    'tags' => ['web-design'],
];

$ch = curl_init('https://urnextdoor.com/api/v1/services');
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": 9,
  "slug": "business-website-in-7-days",
  "url": "/marketplace/business-website-in-7-days",
  "web_url": "https://urnextdoor.com/marketplace/business-website-in-7-days",
  "item": {
    "id": 9,
    "type": "service",
    "slug": "business-website-in-7-days"
  },
  "request_id": "9f8e7d6c5b4a3921"
}

Responses

StatusMeaningCodes
201 CreatedCreated. Published now, or scheduled when scheduled_at was sent.
400 Bad RequestThe body is not a JSON object, or the Idempotency-Key header is malformed.invalid_json, invalid_idempotency_key
401 UnauthorizedNo key, or the key is unknown, malformed, revoked or expired, or the member is not active.missing_api_key, invalid_api_key
403 ForbiddenThe key lacks the scope, or the member may not do this.insufficient_scope, forbidden
404 Not FoundUnknown route or item, or the item is not yours.not_found
409 ConflictConflicts with the current state, or the same Idempotency-Key is still being processed.conflict, idempotency_in_progress
413 Payload Too LargeThe body is over the limit, or the image is over 8 MB.payload_too_large
415 Unsupported Media TypeWrong Content-Type, or a file type that is not allowed.unsupported_media_type
421 Misdirected RequestCalled on a community subdomain. Use https://urnextdoor.com.wrong_host
422 Unprocessable ContentField errors, or an Idempotency-Key reused with a different body.validation_failed, idempotency_key_reused
429 Too Many RequestsOver 60 requests a minute from this member (or too many failed key checks from one address), or today's quota for this action is used up.rate_limited, quota_exceeded
500 Internal Server ErrorOur fault. Safe to retry with the same Idempotency-Key.server_error
503 Service UnavailableThe API is switched off.api_disabled

Post a job

POST https://urnextdoor.com/api/v1/jobs

Publishes a job now, or schedules it. title, body, employment_type, work_mode and experience_level are required (values from GET /job-options). Jobs take featured_image only, no gallery.

  • Auth: your API key (Bearer or X-API-Key)
  • Scope: content
  • Daily quota: counts as job (see limits)
  • Idempotency-Key: supported (see Idempotency)
  • operationId: createJob

Request body

Send Content-Type: application/json.

FieldTypeRequiredDescription
titlestringYesThe job title (plain text).
bodystringYesThe job description as HTML.
employment_typestringYesOne of employment_types from GET /job-options, for example full_time.
work_modestringYesOne of work_modes from GET /job-options, for example remote. Location fields are ignored when it is remote.
experience_levelstringYesOne of experience_levels from GET /job-options, for example mid.
openingsintegerNoNumber of openings. From 1 to 999.
salary_minnumberNoLowest salary in currency, per salary_period.
salary_maxnumberNoHighest salary in currency, per salary_period.
salary_periodstringNoOne of salary_periods from GET /job-options, for example yearly.
currencystringNoThree letter currency code. Pattern: ^[A-Z]{3}$. Default: INR.
application_deadlinestring (date)NoLast day to apply, YYYY-MM-DD.
summarystringNoA short plain text summary shown on cards. Up to 300 characters.
country_codestringNoISO 3166-1 alpha-2 country. Ignored when work_mode is remote.
state_idintegerNoFrom GET /geo. Ignored when work_mode is remote.
district_idintegerNoFrom GET /geo. Ignored when work_mode is remote.
city_idintegerNoFrom GET /geo. Ignored when work_mode is remote.
areastringNoNeighbourhood or area, free text. Ignored when work_mode is remote.
featured_imagestringNoA /storage/... path returned by POST /media (data.url), or any https:// image URL (linked, not copied).
tagsarray of stringNoTopic tags, without the leading #. Example: ["water", "home"].
community_idintegerNoPost inside this community. Use an id from GET /communities/postable. You must be an editor (or above) of it.
communitystringNoAlternative to community_id: the community slug. It is resolved to its id.
scheduled_atstring (date-time)NoPublish later instead of now. ISO 8601 with an offset or Z, at least 5 minutes and at most 180 days ahead. Stored in UTC.

Example

cURL
curl -X POST "https://urnextdoor.com/api/v1/jobs" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "title": "Backend developer (PHP)",
  "body": "<p>Join a small team building tools for local shops.</p><ul><li>3+ years with PHP or Node.js</li><li>Comfortable with MySQL</li></ul>",
  "employment_type": "full_time",
  "work_mode": "remote",
  "experience_level": "mid",
  "openings": 2,
  "salary_min": 900000,
  "salary_max": 1400000,
  "salary_period": "yearly",
  "currency": "INR",
  "application_deadline": "2026-11-30",
  "summary": "Remote, full time, PHP and MySQL.",
  "tags": [
    "php",
    "hiring"
  ]
}'
JavaScript
const res = await fetch("https://urnextdoor.com/api/v1/jobs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    title: "Backend developer (PHP)",
    body: "<p>Join a small team building tools for local shops.</p><ul><li>3+ years with PHP or Node.js</li><li>Comfortable with MySQL</li></ul>",
    employment_type: "full_time",
    work_mode: "remote",
    experience_level: "mid",
    openings: 2,
    salary_min: 900000,
    salary_max: 1400000,
    salary_period: "yearly",
    currency: "INR",
    application_deadline: "2026-11-30",
    summary: "Remote, full time, PHP and MySQL.",
    tags: ["php", "hiring"],
  }),
});
console.log(res.status, await res.json());
Python
import os
import uuid

import requests

api_key = os.environ["UND_API_KEY"]

response = requests.post(
    "https://urnextdoor.com/api/v1/jobs",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "title": "Backend developer (PHP)",
        "body": "<p>Join a small team building tools for local shops.</p><ul><li>3+ years with PHP or Node.js</li><li>Comfortable with MySQL</li></ul>",
        "employment_type": "full_time",
        "work_mode": "remote",
        "experience_level": "mid",
        "openings": 2,
        "salary_min": 900000,
        "salary_max": 1400000,
        "salary_period": "yearly",
        "currency": "INR",
        "application_deadline": "2026-11-30",
        "summary": "Remote, full time, PHP and MySQL.",
        "tags": ["php", "hiring"],
    },
    timeout=30,
)
print(response.status_code, response.json())
PHP
<?php
$apiKey = getenv('UND_API_KEY');

$payload = [
    'title' => 'Backend developer (PHP)',
    'body' => '<p>Join a small team building tools for local shops.</p><ul><li>3+ years with PHP or Node.js</li><li>Comfortable with MySQL</li></ul>',
    'employment_type' => 'full_time',
    'work_mode' => 'remote',
    'experience_level' => 'mid',
    'openings' => 2,
    'salary_min' => 900000,
    'salary_max' => 1400000,
    'salary_period' => 'yearly',
    'currency' => 'INR',
    'application_deadline' => '2026-11-30',
    'summary' => 'Remote, full time, PHP and MySQL.',
    'tags' => ['php', 'hiring'],
];

$ch = curl_init('https://urnextdoor.com/api/v1/jobs');
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": 23,
  "slug": "backend-developer-php",
  "url": "/jobs/backend-developer-php",
  "web_url": "https://urnextdoor.com/jobs/backend-developer-php",
  "item": {
    "id": 23,
    "type": "job",
    "slug": "backend-developer-php"
  },
  "request_id": "9f8e7d6c5b4a3921"
}

Responses

StatusMeaningCodes
201 CreatedCreated. Published now, or scheduled when scheduled_at was sent.
400 Bad RequestThe body is not a JSON object, or the Idempotency-Key header is malformed.invalid_json, invalid_idempotency_key
401 UnauthorizedNo key, or the key is unknown, malformed, revoked or expired, or the member is not active.missing_api_key, invalid_api_key
403 ForbiddenThe key lacks the scope, or the member may not do this.insufficient_scope, forbidden
404 Not FoundUnknown route or item, or the item is not yours.not_found
409 ConflictConflicts with the current state, or the same Idempotency-Key is still being processed.conflict, idempotency_in_progress
413 Payload Too LargeThe body is over the limit, or the image is over 8 MB.payload_too_large
415 Unsupported Media TypeWrong Content-Type, or a file type that is not allowed.unsupported_media_type
421 Misdirected RequestCalled on a community subdomain. Use https://urnextdoor.com.wrong_host
422 Unprocessable ContentField errors, or an Idempotency-Key reused with a different body.validation_failed, idempotency_key_reused
429 Too Many RequestsOver 60 requests a minute from this member (or too many failed key checks from one address), or today's quota for this action is used up.rate_limited, quota_exceeded
500 Internal Server ErrorOur fault. Safe to retry with the same Idempotency-Key.server_error
503 Service UnavailableThe API is switched off.api_disabled

Last updated