---
name: groups-io-api
description: Use the Groups.io v1 HTTP API safely and reliably. Apply when an agent needs to read or modify Groups.io groups, subscriptions, messages, members, events, drafts, chats, files, photos, polls, wikis, or related resources; authenticate with an API key; paginate results; or diagnose an API error.
---

# Use the Groups.io API

Use this guide with the endpoint reference at `https://groups.io/api`. Confirm the exact endpoint, parameters, permissions, and response object there before making a request. The API is marked alpha and its documentation may lag the deployed server.

## Set the request basics

- Use `https://groups.io` as the default origin and `/api/v1/...` as the endpoint path.
- Use the enterprise domain as the origin when the request must be scoped to an enterprise site.
- Prefer an API key sent as `Authorization: Bearer <key>`.
- Never print, log, commit, or repeat an API key. Read it from an environment variable or secret store.
- Send GET parameters in the query string.
- Send POST parameters as `application/x-www-form-urlencoded` unless the endpoint explicitly documents another content type.
- Omit `csrf` when using an API key. Cookie-authenticated state-changing requests generally require the user's `csrf_token`.
- Treat IDs and page tokens as opaque values. Preserve them exactly and do not infer meaning from them.

Use a request pattern like:

```bash
curl --fail-with-body --silent --show-error \
  "https://groups.io/api/v1/getsubs?limit=100" \
  -H "Authorization: Bearer ${GROUPS_IO_API_KEY}"
```

For a POST request:

```bash
curl --fail-with-body --silent --show-error \
  "https://groups.io/api/v1/updatedraft" \
  -H "Authorization: Bearer ${GROUPS_IO_API_KEY}" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "draft_id=123" \
  --data-urlencode "subject=Updated subject"
```

Use `--data-urlencode`, `URLSearchParams`, or the language's URL/form encoder. Do not concatenate untrusted values into URLs or request bodies.

## Choose and verify an endpoint

Search the API reference by the literal `/api/v1/<endpoint>` path or visible method title. Do not rely solely on in-page links: some generated anchors are incorrect or duplicated.

Common discovery paths include:

- Account and subscriptions: `getuser`, `getsubs`, `getsub`, `updatesub`
- Groups and permissions: `getgroup`, `getsubgroups`, `getperms`, `getorg`
- Archives: `gettopics`, `gettopic`, `updatetopic`, `getmessages`, `getmessage`, `searcharchives`
- Members: `getmembers`, `getmember`, `searchmembers`, `updatemember`
- Drafts and posting: `newdraft`, `updatedraft`, `uploadattachments`, `postdraft`
- Events: `getevents`, `getevent`, `rsvp`, `addevent`, `updateevent`
- Other resources: chats, files, photos, polls, wikis, hashtags, databases, notifications, and pending messages each have their own section.

Before a call, establish:

1. The HTTP method and exact path.
2. Required identifiers and whether alternatives such as `group_id` or `group_name` are allowed.
3. Required group permissions or membership state.
4. Whether the operation mutates data or triggers notifications, email, posting, deletion, or asynchronous work.
5. The documented success object and endpoint-specific errors.

Ask for confirmation before a consequential mutation unless the user already authorized that specific action. Never substitute a similarly named endpoint.

## Update a topic

Use `POST /api/v1/updatetopic` to change an existing topic. The caller must have the group's `edit_archives` permission.

- Send the required `topic_id`.
- Optionally send `subject`, `is_moderated`, `is_closed`, `is_sticky`, or `reply_to`. Omitted fields remain unchanged.
- A supplied `subject` may end with hashtags. Those trailing hashtags become the topic's hashtags, and existing hashtags omitted from the supplied subject are removed. Omitting `subject` preserves both the current subject and hashtags.
- Send boolean fields as the literal strings `true` or `false`. Other values are ignored rather than treated as false.
- Valid `reply_to` values are `thread_reply_group_default`, `thread_reply_to_group`, `thread_reply_to_sender`, `thread_reply_to_moderators`, `thread_reply_to_group_and_sender`, `thread_reply_only_to_sender`, and `thread_reply_to_followers_only`.
- Setting `is_closed=true` through the API locks the topic without posting the group's locked-topic member notice.
- Expect the updated `topic` object on success.

For example:

```bash
curl --fail-with-body --silent --show-error \
  "https://groups.io/api/v1/updatetopic" \
  -H "Authorization: Bearer ${GROUPS_IO_API_KEY}" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "topic_id=123" \
  --data-urlencode "is_sticky=true"
```

## Handle responses

Expect JSON for normal object and error responses. Check the HTTP status before decoding the success shape.

Most API failures use HTTP 400 with:

```json
{
  "object": "error",
  "type": "inadequate_permissions",
  "extra": ""
}
```

Branch on `type`; use `extra` only for additional context. Do not match the human-readable text alone. Handle HTTP 429 separately with exponential backoff and jitter. Retry transient server or network failures only when the request is safe to retry; do not automatically retry a mutation unless its idempotency is established.

Common error types include `unauthorized_error`, `bad_request`, `authentication`, `expired`, `rate_limit`, `inadequate_permissions`, `invalid_value`, `server`, and `bad_csrf`. Endpoint-specific values may also occur.

When `extended=true` is supported, expect an array rather than the normal object. Current server code returns the user object first and the endpoint result second. Avoid `extended=true` unless the additional user/subscription data is needed.

## Paginate completely

For endpoints that document pagination:

1. Request the first page without `page_token`.
2. Process `data`.
3. If `has_more` is true, pass `next_page_token` unchanged as the next `page_token`.
4. Stop when `has_more` is false.
5. Set `limit` from 1 through 100; prefer 100 for complete exports unless latency or rate limits favor smaller pages.
6. Keep `sort_field`, `sort_dir`, filters, and group scope unchanged across pages.

Do not treat `next_page_token` as a number even if an example displays one.

## Protect users and data

- Start with read-only endpoints when investigating or planning.
- Show the target group/resource and intended mutation before executing ambiguous destructive actions.
- Do not expose private group content, member data, email addresses, or moderation data beyond the user's request and permissions.
- Do not use login credentials when an API key is available.
- Do not invent IDs, enum values, permissions, or undocumented request fields.
- Redact authorization headers and sensitive response fields from diagnostics.
- For bulk operations, test the selection with a read endpoint and summarize the affected count before mutation.

## Account for current documentation caveats

When repository source is available, prefer active route registrations in `cmd/apiserver/apiserver.go` and endpoint comments beside their handlers over an older generated snapshot.

Known discrepancies in the reviewed source are:

- The active enterprise-info path is `/api/v1/getenterpriseinfo`; generated docs currently show `/api/v1/enterpriseinfo`.
- `appleloginstart` and `appleloginfinal` appear in generated docs, but their route registrations are disabled.
- Topic-summary routes may be absent from older snapshots: `gettopicsummary`, `generatetopicsummary`, and `gettopicsummarystatus` exist in newer server source.
- Generated object and “View Method” links often use hyphens while rendered IDs use underscores. Search by title or literal endpoint instead.
- A dated “Revised” label describes the selected documentation snapshot, not necessarily the running API build.

If docs and the server disagree and no source is available, stop before mutating data and ask the user to confirm the deployed endpoint.

## Report results

Return a concise summary containing:

- The origin, method, and endpoint used, without secrets.
- The scope, filters, and number of records processed.
- Pagination completion status.
- Any skipped or failed records with structured error types.
- For mutations, the confirmed target and the server's returned object or success indicator.
