---
title: "Group signups by company email domain"
method: GET
path: "/v1/admin/opportunities/companies"
tags: ["Admin"]
---

# Group signups by company email domain

`GET /v1/admin/opportunities/companies`

## Request

- Base URL: `https://api.openworklabs.com`
- URL: `https://api.openworklabs.com/v1/admin/opportunities/companies`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

Platform-admin-only, paginated. Groups accounts with a verified, non-personal email domain across every organization they joined: signups, first signup, latest sign-in still on record, organizations, people observed using the app in the last 30 days, highest stored plan, current paid subscription, and whether a platform admin recorded outreach for any of those organizations. Defaults to active companies nobody has contacted. A domain does not establish employment and organizations are never merged. No content, credentials, Stripe calls or external enrichment.

## Query parameters

- `activity` 'active' | 'all'
- `outreach` 'not_contacted' | 'contacted' | 'any'
- `billing` 'any' | 'paying' | 'not_paying'
- `sort` 'active' | 'signups' | 'recent' | 'signin'
- `search` string
- `limit` integer
- `cursor` string
- `offset` string

## Response `200`

Signup companies returned.

- AdminSignupCompanies
  - `from` string, date-time, required
  - `to` string, date-time, required
  - `generatedAt` string, date-time, required
  - `nextCursor` string, nullable, required: Pass as cursor with the same filters and sort to continue; null on the last page.
  - `companies` object[], required
    - `domain` string, required
    - `signups` integer, required
    - `organizations` integer, required
    - `activeUsers` integer, required
    - `firstSignupAt` string, date-time, required
    - `lastSignInAt` string, date-time, nullable, required
    - `billing` object, required
      - `plan` 'free' | 'team' | 'enterprise', required
      - `paying` boolean, required
      - `modelsAddOn` boolean, required
    - `outreach` object, required
      - `status` 'not_contacted' | 'contacted', required
      - `lastContactedAt` string, date-time, nullable, required
    - `workspaces` object[], required
      - `id` string, required
      - `name` string, required
      - `members` integer, required
  - `page` object, required
    - `limit` integer, required
    - `total` integer, required
    - `returned` integer, required
    - `hasMore` boolean, required

## Other responses

- `400`: Invalid report filters.
- `401`: Authentication required.
- `403`: Platform admin access required.

## Changes

- **2026-10-23** `c93387179b31`: 1 breaking, 8 info
  - the response property `nextCursor` became nullable for the status `200`
  - response property `details/items/path/items/` list-of-types was narrowed by removing types `number` from media type `application/json` of response `400`
  - response property `nextCursor` list-of-types was narrowed by removing types `null` from media type `application/json` of response `200`
  - the `companies/items/firstSignupAt` response's property pattern was changed from `^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$` to `^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$` for the status `200`
  - …5 more
- **2026-10-22** `6b535fe28240`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/openworklabs/apis/den-api/changes/v1/admin/opportunities/companies/get.md)

---

[API](https://skmtc.dev/openworklabs/apis/den-api.md) - [All operations](https://skmtc.dev/openworklabs/apis/den-api/llms.txt) - [OpenAPI document](https://skmtc.dev/openworklabs/apis/den-api/revisions/8170cf4a92ca?raw)
