# ActivityPub Federation API

Forgejo supports ActivityPub federation as part of its ForgeFed implementation. These endpoints enable server-to-server communication between federated Forgejo (and compatible) instances.

**Base path:** `${FORGEJO_URL}/api/v1/activitypub`

## Key Concepts

- ActivityPub endpoints use **numeric IDs**, not usernames or repository names
- Responses are JSON-LD with ActivityStreams context
- The instance actor represents the Forgejo server itself for federation
- Public key infrastructure is used for HTTP signature verification between federated instances
- POST (inbox/outbox) endpoints require HTTP signatures and are for server-to-server communication, not direct client use

---

## Instance Actor (3 endpoints)

The instance actor is an `Application` type that represents the Forgejo server itself.

### GET `/activitypub/actor`

Returns the instance's Actor object.

**Response fields:**
- `@context` - JSON-LD context (ActivityStreams + Security vocabulary)
- `id` - Actor URL
- `type` - `"Application"`
- `url` - Instance base URL
- `inbox` - Inbox endpoint URL
- `outbox` - Outbox endpoint URL
- `preferredUsername` - Instance username (typically `"ghost"`)
- `publicKey` - Object containing `id`, `owner`, and `publicKeyPem` for HTTP signature verification

**Example response:**
```json
{
  "@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"],
  "id": "https://git.example.com/api/v1/activitypub/actor",
  "type": "Application",
  "url": "https://git.example.com/",
  "inbox": "https://git.example.com/api/v1/activitypub/actor/inbox",
  "outbox": "https://git.example.com/api/v1/activitypub/actor/outbox",
  "preferredUsername": "ghost",
  "publicKey": {
    "id": "https://git.example.com/api/v1/activitypub/actor#main-key",
    "owner": "https://git.example.com/api/v1/activitypub/actor",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n"
  }
}
```

```bash
curl -s "${FORGEJO_URL}/api/v1/activitypub/actor" \
  -H "Accept: application/activity+json"
```

### POST `/activitypub/actor/inbox`

Send an activity to the instance inbox. Used for server-to-server federation (requires HTTP signatures).

### POST `/activitypub/actor/outbox`

Display the instance outbox. Currently always returns an empty collection.

---

## Repository Actor (3 endpoints)

Repository actors use the **numeric repository ID**, not the `owner/repo` name.

### GET `/activitypub/repository-id/{repository-id}`

Returns the Repository actor for a given numeric repository ID.

```bash
# Get repository actor (using numeric repo ID, e.g., 42)
curl -s "${FORGEJO_URL}/api/v1/activitypub/repository-id/{repository_id}" \
  -H "Accept: application/activity+json"
```

### POST `/activitypub/repository-id/{repository-id}/inbox`

Send an activity to the repository inbox. Server-to-server only (requires HTTP signatures).

### POST `/activitypub/repository-id/{repository-id}/outbox`

Display the repository outbox.

---

## User (Person) Actor (5 endpoints)

User actors use the **numeric user ID**, not the username.

### GET `/activitypub/user-id/{user-id}`

Returns the Person actor for a given numeric user ID.

```bash
# Get user actor (using numeric user ID, e.g., 1)
curl -s "${FORGEJO_URL}/api/v1/activitypub/user-id/{user_id}" \
  -H "Accept: application/activity+json"
```

### GET `/activitypub/user-id/{user-id}/activities/{activity-id}`

Get a specific activity object by its ID.

```bash
curl -s "${FORGEJO_URL}/api/v1/activitypub/user-id/{user_id}/activities/{activity_id}" \
  -H "Accept: application/activity+json"
```

### GET `/activitypub/user-id/{user-id}/activities/{activity-id}/activity`

Get a specific activity (the wrapper Activity object, as opposed to the inner object).

```bash
curl -s "${FORGEJO_URL}/api/v1/activitypub/user-id/{user_id}/activities/{activity_id}/activity" \
  -H "Accept: application/activity+json"
```

### POST `/activitypub/user-id/{user-id}/inbox`

Send an activity to the user inbox. Server-to-server only (requires HTTP signatures).

### GET `/activitypub/user-id/{user-id}/outbox`

List the user's recorded activity as an OrderedCollection.

```bash
curl -s "${FORGEJO_URL}/api/v1/activitypub/user-id/{user_id}/outbox" \
  -H "Accept: application/activity+json"
```

---

## Endpoint Summary

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/activitypub/actor` | Instance actor |
| POST | `/activitypub/actor/inbox` | Instance inbox (S2S) |
| POST | `/activitypub/actor/outbox` | Instance outbox (empty) |
| GET | `/activitypub/repository-id/{repository-id}` | Repository actor |
| POST | `/activitypub/repository-id/{repository-id}/inbox` | Repository inbox (S2S) |
| POST | `/activitypub/repository-id/{repository-id}/outbox` | Repository outbox |
| GET | `/activitypub/user-id/{user-id}` | User (Person) actor |
| GET | `/activitypub/user-id/{user-id}/activities/{activity-id}` | Specific activity object |
| GET | `/activitypub/user-id/{user-id}/activities/{activity-id}/activity` | Specific activity wrapper |
| POST | `/activitypub/user-id/{user-id}/inbox` | User inbox (S2S) |
| GET | `/activitypub/user-id/{user-id}/outbox` | User outbox |

**S2S** = Server-to-server only, requires HTTP signatures for federation.

## Notes

- To find a repository's numeric ID, use `GET /api/v1/repos/{owner}/{repo}` and read the `id` field.
- To find a user's numeric ID, use `GET /api/v1/users/{username}` and read the `id` field.
- Federation must be enabled in the Forgejo instance configuration for these endpoints to function.
