# OrgOrg API v1 — Groups — instructions for AI agents

This document describes the Groups endpoints of the OrgOrg v1 REST API. Fetch it from https://orgorg.com/docs/api/v1/groups/agents.md. The full API is documented at https://orgorg.com/docs/api/v1/agents.md.

## Basics

- Base URL: `https://orgorg.com`. All endpoint paths below are relative to it.
- Every request requires an `Authorization: Bearer <token>` header.
- `GET` endpoints take parameters in the URL query string. `POST` endpoints take a JSON body with a `Content-Type: application/json` header.
- All responses are JSON. A non-2xx status means the request failed; the body describes the problem.
- Endpoints are stable, but new response fields may be added without notice — ignore fields you do not recognize.

## Getting a token

Tokens are created by a signed-in user at https://orgorg.com/docs/credentials and inherit that user's permissions in their organization. If you do not have a token, ask your user to create one there. Verify a token works with:

```sh
curl "https://orgorg.com/api/v1/auth/test" \
  -H "Authorization: Bearer $ORGORG_API_TOKEN"
```

A valid token returns `{ "ok": true, ... }`.

## Groups

The groups of people that a rule keeps current. List them, read the sync destinations of one, and sync one to Slack channels. The orgorg CLI uses these endpoints for its groups commands. Human-readable docs: https://orgorg.com/docs/api/v1/groups

### List groups

`GET /api/v1/groups`

List the groups you can see, with the rule and the member count of each. Requires groups:read (or :write).

Parameters: none.

Example request:

```sh
curl -X GET "https://orgorg.com/api/v1/groups" \
  -H "Authorization: Bearer $ORGORG_API_TOKEN"
```

Response shape:

```ts
{
  data: {
    id: string;
    name: string;
    rule: string;
    memberCount: number;
    isUnlisted: boolean;
    lastSuccessfulRun: number | null;
    createdAt: number;
    updatedAt: number;
  }[]
}
```

### List sync destinations of a group

`GET /api/v1/groups/destinations`

The sync destinations of one group (Slack channels, Google Groups, badges), with the last run of each. A Slack destination names its channel when the OrgOrg Slack app can see it. Requires groups:read (or :write).

Parameters:

- `group` (string, required) — The group: its id (the last segment of its URL, /groups/<id>) or its exact name.

Example request:

```sh
curl -X GET "https://orgorg.com/api/v1/groups/destinations?group=GROUP_ID" \
  -H "Authorization: Bearer $ORGORG_API_TOKEN"
```

Response shape:

```ts
{
  data: {
    id: string;
    type: 'SlackBot' | 'SlackUser' | 'GoogleGroups' | 'OrgOrgBadge';
    destinationId: string;
    channel: string | null;
    addOnly: boolean;
    lastRun: number | null;
    lastSuccessfulRun: number | null;
    lastRunSucceeded: boolean | null;
  }[]
}
```

### Sync a group to Slack channels

`POST /api/v1/groups/sync-slack`

Make each matching Slack channel a sync destination of the group, through the OrgOrg Slack app, then run the sync. The app invites each member of the group to each channel. Without addOnly it also removes everyone else from the channel, except bots. The app sees a private channel only after /invite. Run it again to take up a channel made later. You must be able to edit the group. Requires groups:write.

Parameters:

- `group` (string, required) — The group: its id (the last segment of its URL, /groups/<id>) or its exact name.
- `channels` (string, required) — Channel names, comma-separated. A `*` matches any text: `internal_*` names every channel whose name starts with internal_.
- `addOnly` (boolean, optional) — True keeps everyone who is in a channel already. Default false: the channel becomes the group.

Example request:

```sh
curl -X POST "https://orgorg.com/api/v1/groups/sync-slack" \
  -H "Authorization: Bearer $ORGORG_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "group": "GROUP_ID",
    "channels": "internal_*"
  }'
```

Response shape:

```ts
{
  data: {
    group: { id: string; name: string };
    addOnly: boolean;
    destinations: {
      destinationId: string;
      channelId: string;
      channel: string;
      isPrivate: boolean;
      created: boolean;
    }[];
    unmatched: string[];
    members: number;
  }
}
```
