# Authors and claims

Many people who wrote on the old platform have not joined Zen Social when you move their posts in. Their posts can
still come in under their name, and be handed to them later, when they have joined. Handing them over is a **claim**.
A claim can be undone.

## Names from the old platform

A post created with `author` instead of `author_id` (see [Posts](posts.md#who-wrote-it-author_id-or-author)) shows the
name you sent, with no profile and no link:

```json
{"author": {"external_id": "fb-user-1002", "name": "Ole Berg"}}
```

The `external_id` in `author` is your own id for that person on the old platform. It is what a claim works with: the
claim hands over **every** post of this community that you created with that author `external_id`. So:

- Use the same author `external_id` for all posts by the same person, and a different one for every person, even when
  two people share a name.
- **Send the post's own `external_id` too.** Zen Social remembers authors only for posts created with an
  `external_id`. A post created with an `author` name but without its own `external_id` can never be claimed, and
  stays under the old name for good.

## Claim: `POST /authors/:author_external_id/claim`

When the person has joined and you have found them in `GET /members`, the claim makes them the author of all their
imported posts.

**Confirm with the admin first.** Show them the name match you intend to make (for example "Ole Berg on Facebook, 2
posts → Ole Berg, member `Qm3TzK8pWn2D`") and wait for their yes. When a name fits more than one member, or fits only
roughly, ask; do not guess.

```sh
curl "$API/authors/fb-user-1002/claim" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"member_id": "Qm3TzK8pWn2D"}'
```

`member_id` is the member's `id` from [Members](members.md). Answers `201 Created`:

```json
{"claimed": 2, "claimed_ids": [9002, 9003], "skipped": 0, "skipped_ids": []}
```

`claimed_ids` are the posts that now belong to the member; `skipped_ids` are posts that were not handed over (below).

Other answers:

- `404 not_found`: this community never imported a post with that author `external_id`.
- `422 invalid`, with `details.member_id`: `member_id` is missing, or is not a member of this community.

What a claim does:

- The member becomes the author of those posts, as if they had written them: their name and picture show, and the
  posts link to their profile.
- **Nobody is told**, the member included. The posts keep their dates, show no "edited" mark, and nothing moves in
  anyone's feed. The admin may want to tell the member themselves.
- Deleted posts, and posts turned into events in the app, are left alone and not listed.
- A claim can be sent again. Posts already claimed for the same member count as claimed again. A claim for a
  **different** member moves the posts to that member: this is how a wrong match is put right.
- A claimed post can still be re-run, changed and deleted through the API (see
  [Who may change which post](posts.md#who-may-change-which-post)). A re-run never changes its author back.
- A claimed post is the member's own. If they delete their account, it goes with it, like any post of theirs.

## What a claim skips

A post is skipped, and listed in `skipped_ids`, when:

- **the member is not in every one of its circles.** Posts are never handed to someone who cannot see them. Tell the
  admin which circle it is; once the member has joined it in the app, send the same claim again and the skipped posts
  are claimed then.
- **the admin can no longer post in one of its circles.** Ask the admin to rejoin that circle, or have an admin who can
  post there make a key.

## Undo: `DELETE /authors/:author_external_id/claim`

A claim made by mistake is undone with `DELETE` on the same address. Confirm with the admin first, as for a claim.

```sh
curl -X DELETE "$API/authors/fb-user-1002/claim" -H "Authorization: Bearer $KEY"
```

Answers `200 OK`:

```json
{"released": 2, "released_ids": [9002, 9003], "skipped": 0, "skipped_ids": []}
```

The posts go back to the name from the old platform, exactly as they were imported, again without telling anyone.
Posts that were never claimed are left as they are and not listed. A post in a circle the admin can no longer post in
is skipped and listed in `skipped_ids`. `404 not_found` when this community never imported a post with that
author `external_id`.

## The author id in the address

The author `external_id` is part of the address, so percent-encode it: a space is `%20`, and a slash **must** be sent
as `%2F`. Letters, digits, `-`, `_`, `.` and `:` can stay as they are.

For the author `external_id` `old-site/users/17`:

```sh
curl "$API/authors/old-site%2Fusers%2F17/claim" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"member_id": "Qm3TzK8pWn2D"}'
```

## Example: three posts from two Facebook authors

The admin is moving the Facebook group's "Garden Swap" posts into the circle with id `412`. Three posts, by two
people:

- Karen Holm wrote one post. She is already a member: `GET /members` lists her as `EveABqLyto9L`, and she is in the
  Garden Swap circle.
- Ole Berg wrote two. He has not joined yet. His Facebook user id is `1002`.

You have agreed the plan with the admin. The first post is Karen's, under her member id:

```sh
curl "$API/posts" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"external_id": "fb-post-5001", "circle_ids": [412], "author_id": "EveABqLyto9L", "created_at": "2023-04-15T10:00:00Z", "content": "Who has spare tomato seedlings?\n\nI can swap basil."}'
```

The other two are Ole's, under his name, each with its own `external_id` and both with the same author `external_id`:

```sh
curl "$API/posts" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"external_id": "fb-post-5002", "circle_ids": [412], "author": {"external_id": "fb-user-1002", "name": "Ole Berg"}, "created_at": "2023-04-16T08:15:00Z", "content": "I have six seedlings for you, Karen."}'
```

```sh
curl "$API/posts" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"external_id": "fb-post-5003", "circle_ids": [412], "author": {"external_id": "fb-user-1002", "name": "Ole Berg"}, "created_at": "2023-05-02T18:30:00Z", "content": "The swap table is up!", "image_urls": ["https://example.org/swap-table.jpg"]}'
```

Each answers `201 Created`, with ids `9001`, `9002` and `9003`. Nobody is told. Ask the admin to look at the circle
in the app: the posts sit in April and May 2023, and Ole's show his name without a profile.

Weeks later, Ole accepts the admin's invitation and joins Garden Swap. `GET /members` now lists him:

```json
{"id": "Qm3TzK8pWn2D", "name": "Ole Berg", "avatar_url": null, "circles": [{"id": 412, "name": "Garden Swap"}]}
```

Tell the admin: "Ole Berg on Facebook (2 posts) looks like the member Ole Berg (`Qm3TzK8pWn2D`). Shall I hand his
posts to him?" When they say yes:

```sh
curl "$API/authors/fb-user-1002/claim" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"member_id": "Qm3TzK8pWn2D"}'
```

It answers `201 Created` with `{"claimed": 2, "claimed_ids": [9002, 9003], "skipped": 0, "skipped_ids": []}`. Both
posts are now Ole's. Karen's post was never part of it.

If the admin later says it was a different Ole, undo it with `DELETE "$API/authors/fb-user-1002/claim"`, and the
posts show "Ole Berg" from Facebook again.
