# `not_found`: Not found

> HTTP 404. Nothing this credential may see exists at that identifier. It may not exist at all, or your credential may not be allowed to know it does.

The identifier in the path (an article, tag, subscriber, thread, message, highlight, sender, domain, send, delivery attempt, API key or user) does not name anything this credential can see. The message names the kind of thing, for example "No such article."

Commune answers `404` rather than `403` wherever a `403` would confirm that something private exists. So a `404` can mean the object does not exist, or that it exists in a newsletter your credential does not reach or cannot read that part of. A newsletter in the path is different: a newsletter your credential does not reach is a `403` (`forbidden`), even when the handle is simply wrong.

## Why it happens, and how to fix it

### 1. The identifier is wrong, or the object is gone

The id has a typo, was truncated, or names something that was deleted (a deleted tag, for example). Identifiers are exact: most are UUIDs, a user id is an opaque string, and none of them are email addresses or slugs.

**Fix:** Take the id from a list operation rather than building it, for example `GET /newsletters/{newsletter}/articles` or `GET /newsletters/{newsletter}/tags`, and pass it back unchanged.

### 2. The object is in a newsletter your credential cannot read it in

The object exists, but it belongs to a newsletter this credential does not reach, or reaches without the family that covers it (a subscriber needs `audience`, an article `content`, and so on). It is reported as not found so that ids cannot be probed across newsletters.

**Fix:** Check which newsletter the object belongs to and call `GET /newsletters` to confirm your credential reaches it. Then check the key's permissions on [Settings, API keys](https://usecommune.com/settings/api-keys); if the family is missing, mint a key that holds it.

### 3. A read-only credential asked for something unpublished

A credential holding only `read` on a newsletter sees it the way a reader does, so drafts, scheduled articles and threads that are not public are not visible to it and answer `404` when addressed directly.

**Fix:** Use a credential that holds `write` in one of the newsletter's families to work with unpublished content.

### 4. The id is of the wrong kind

An id from one resource was passed where another is expected: a message id to `GET /threads/{thread}`, a subscriber's user id to `GET /subscribers/{subscriber}`, a send id to `GET /articles/{article}`.

**Fix:** Follow the relationship the resource gives you. A message carries its `thread`, a subscriber has its own `id`, a send references its `article`.

### 5. The delivery attempt belongs to another newsletter

On `GET /delivery-attempts/{attempt}` and `POST /delivery-attempts/{attempt}/replay`, the attempt is looked up in one newsletter: the `newsletter` query parameter, or your credential's only newsletter. An attempt from a different one is not found.

**Fix:** Send `?newsletter=` with the newsletter the attempt was listed under in `GET /newsletters/{newsletter}/delivery-attempts`.

## Retrying

No: the answer stays the same until you address an id this credential can see, or use a credential that can see this one.

## Example response

```json
{
  "error": {
    "code": "not_found",
    "message": "No such article.",
    "request_id": "req_01j9c8h1q7m3n4p5r6s7t8u9v0",
    "docs_url": "https://usecommune.dev/errors/not_found"
  }
}
```

Often confused with: [`forbidden`](https://usecommune.dev/errors/forbidden.md), [`insufficient_scope`](https://usecommune.dev/errors/insufficient_scope.md).
