# Edit your posts and other content

> Change your own posts, questions, polls, MCQs, answers, comments, services and jobs with the API: send only what changes, add images, archive, resolve.

Source: https://docs.urnextdoor.com/guides/edit-content/

A key edits **your own** items: the ones you created, on the website, in the app or through the API. Editing anyone else's, even in a community you moderate, answers `403 not_your_content`; moderators edit other members' items on the website.

**Scope:** `edit` · **Quota:** `edit`, one unit per successful edit

## Send only what changes

Every edit is a `PUT` with only the fields you change. Everything you do not send is kept:

**cURL**

```bash
curl -X PUT "https://urnextdoor.com/api/v1/posts/41" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "Five easy ways to save water at home (updated)"
}'
```

**JavaScript**

```js
const res = await fetch("https://urnextdoor.com/api/v1/posts/41", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Five easy ways to save water at home (updated)",
  }),
});
console.log(res.status, await res.json());
```

**Python**

```python
import os

import requests

api_key = os.environ["UND_API_KEY"]

response = requests.put(
    "https://urnextdoor.com/api/v1/posts/41",
    headers={
        "Authorization": f"Bearer {api_key}",
    },
    json={
        "title": "Five easy ways to save water at home (updated)",
    },
    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 (updated)',
];

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

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

| Item | Endpoint | Fields as in |
| --- | --- | --- |
| Post | `PUT /api/v1/posts/{id}` | [Create a post](https://docs.urnextdoor.com/guides/create-post.md) |
| Question | `PUT /api/v1/questions/{id}` | [Ask a question](https://docs.urnextdoor.com/guides/create-question.md) |
| Poll | `PUT /api/v1/polls/{id}` | [Create a poll](https://docs.urnextdoor.com/guides/create-poll.md), plus `is_closed`. Options cannot change. |
| MCQ | `PUT /api/v1/mcqs/{id}` | [Create an MCQ](https://docs.urnextdoor.com/guides/create-mcq.md). The correct option is locked once anyone answered. |
| Answer | `PUT /api/v1/answers/{id}` | `body` |
| Comment or reply | `PUT /api/v1/comments/{id}` | `body` |
| Service | `PUT /api/v1/services/{id}` | [List a service](https://docs.urnextdoor.com/guides/create-service.md). `packages`, when sent, replace them all. |
| Job | `PUT /api/v1/jobs/{id}` | [Post a job](https://docs.urnextdoor.com/guides/create-job.md) |

Three details make edits safe for a tool that only knows what it wants to change:

- **Tags are kept.** Changing the title or body keeps the item's tags. Send `tags` only to replace them.
- **A new cover keeps the gallery.** `featured_image` alone becomes the new cover, in front of the images already there. Send `gallery` to replace the whole gallery.
- **Jobs keep every field.** The salary, location, cover and tags of a job stay as they are unless you send them.

Outside images in an edit are imported, as on a create. See [Upload images](https://docs.urnextdoor.com/guides/upload-images.md).

## Add images to an item

`POST /api/v1/gallery` adds images, by link or as ChatGPT files, to the gallery of your post, question, poll, MCQ or service, after the ones it has. `cover: true` makes the first new image the cover. It also needs the `media` scope.

**cURL**

```bash
curl -X POST "https://urnextdoor.com/api/v1/gallery" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "type": "post",
  "id": 41,
  "image_urls": [
    "https://example.com/garden.jpg"
  ],
  "cover": true
}'
```

**JavaScript**

```js
const res = await fetch("https://urnextdoor.com/api/v1/gallery", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    type: "post",
    id: 41,
    image_urls: ["https://example.com/garden.jpg"],
    cover: true,
  }),
});
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/gallery",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "type": "post",
        "id": 41,
        "image_urls": ["https://example.com/garden.jpg"],
        "cover": True,
    },
    timeout=30,
)
print(response.status_code, response.json())
```

**PHP**

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

$payload = [
    'type' => 'post',
    'id' => 41,
    'image_urls' => ['https://example.com/garden.jpg'],
    'cover' => true,
];

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

## Set a state, safely

These set a state rather than flip it: sending the state an item is already in changes nothing and answers `changed: false`, so a retry can never undo itself.

| What | Endpoint | Body |
| --- | --- | --- |
| Archive or restore an item | `PUT /api/v1/archive` | `{"type": "post", "id": 41, "archived": true}` |
| Mark your question resolved | `PUT /api/v1/questions/{id}/resolved` | `{"resolved": true}` |
| Accept an answer to your question | `PUT /api/v1/answers/{id}/accepted` | `{"accepted": true}` |
| Close or reopen your job | `POST /api/v1/jobs/{id}/close`, `POST /api/v1/jobs/{id}/reopen` | none |

Archiving hides an item from everyone but you. Restoring touches only archived items, so it never publishes a draft.

**cURL**

```bash
curl -X PUT "https://urnextdoor.com/api/v1/archive" \
  -H "Authorization: Bearer $UND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "type": "post",
  "id": 41,
  "archived": true
}'
```

**JavaScript**

```js
const res = await fetch("https://urnextdoor.com/api/v1/archive", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.UND_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    type: "post",
    id: 41,
    archived: true,
  }),
});
console.log(res.status, await res.json());
```

**Python**

```python
import os

import requests

api_key = os.environ["UND_API_KEY"]

response = requests.put(
    "https://urnextdoor.com/api/v1/archive",
    headers={
        "Authorization": f"Bearer {api_key}",
    },
    json={
        "type": "post",
        "id": 41,
        "archived": True,
    },
    timeout=30,
)
print(response.status_code, response.json())
```

**PHP**

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

$payload = [
    'type' => 'post',
    'id' => 41,
    'archived' => true,
];

$ch = curl_init('https://urnextdoor.com/api/v1/archive');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

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

## Errors

| Status and code | Cause |
| --- | --- |
| `403 not_your_content` | The item is not yours |
| `403 forbidden` | You cannot move it into that community (editors and above only) |
| `404 not_found` | No item with that id |
| `409 conflict` | The MCQ's answer is locked, or the job is scheduled |
| `422 validation_failed` | A field is empty or wrong; see `errors` |

## Next steps

- [Upload images](https://docs.urnextdoor.com/guides/upload-images.md).
- [Manage scheduled content](https://docs.urnextdoor.com/guides/manage-scheduled.md) for items that are not live yet.
- [API reference: Editing](https://docs.urnextdoor.com/reference/editing.md).
