General

Purpose

The Numero GraphQL API exposes a limited, curated set of common actions — the things customers do over and over again (pulling exports, managing lists, scheduling recurring exports, reading transfers, etc.). It is intentionally scoped rather than a full mirror of the application.

If you need functionality that isn't covered here, request it: [email protected].

Authentication

1. User access & role

Access is tied to a dedicated API user on each platform you want to read data from (for example, [email protected]). Create that user, then let us know — we grant it the special permission required to reach the GraphQL API.

💡 Use a separate API user per integration rather than a real person's login. It keeps permissions auditable and avoids breaking your integration when staff change.

2. API key & headers

Every request is authenticated with two headers:

Authorization: Bearer <API_KEY>
NUMERO-ACCOUNT-ID: <ACCOUNT_ID>
Header Description
Authorization Bearer followed by your API key. Identifies the API user.
NUMERO-ACCOUNT-ID The account (committee / platform) whose data you're querying.

3. Finding your account IDs

A single API user can belong to many accounts. To list every account ID the user can act on (handy when looping over accounts in a script), call the following while logged in as that user:

GET https://app.numero.ai/api/users/current

4. Keep your key secure 🔒

5. Making a request

The GraphQL endpoint is:

POST https://app.numero.ai/graphql

A complete request looks like:

curl https://app.numero.ai/graphql \
  -H "Authorization: Bearer $NUMERO_API_KEY" \
  -H "NUMERO-ACCOUNT-ID: $NUMERO_ACCOUNT_ID" \
  -H "Content-Type: application/json" \
  -d '{"query":"query { listsCollection(params: {limit: 10}) { lists { id name } } }"}'

You can build and test queries interactively in GraphiQL at app.numero.ai/graphiql while logged in as the API user.

Every operation below includes a runnable curl example. They all assume $NUMERO_API_KEY and $NUMERO_ACCOUNT_ID are set in your environment, and (except for the imports file upload) send the query as a JSON body — swap in any query/variables from the GraphiQL links.

Conventions

These patterns are shared across every endpoint, so they're documented once here and not repeated for each one.

The params wrapper

List (collection) and statistics fields take a single params argument that wraps filters and pagination, e.g. listsCollection(params: $dataParams).

Filtering

Filters are a logical tree. Combine conditions with _and / _or, and apply per-field operators:

{
  "filters": {
    "_and": [
      { "sentAt": { "_ltRelative": { "quantity": 10, "direction": "ago", "unit": "day" } } }
    ]
  }
}

Example — records created or updated in the last day. The same filters also power the createList, createExport, createScheduledExport, and createContactTransfer mutations, where they define which records are included:

{ "filters": { "_and": [ { "updatedAt": { "_ltRelative": { "quantity": 1, "direction": "ago", "unit": "day" } } } ] } }

Swap updatedAt for createdAt to filter on creation time.

Pagination

Use limit and offset. Keep limit within reason (≤ 100); page through larger result sets by advancing offset (page 2 = limit: 100, offset: 100).

⚡ Query only the fields you need. Don't request every field — selecting a narrow set dramatically improves performance and throughput for you and for the platform.

Statistics & totalCount

Some collections — mainly the analytics-oriented ones (contacts, contributions, interactions, pledges, rsvps, submissions, emailBroadcasts, textBroadcasts, and the broadcast-message collections) — expose a sibling …Statistics(params:) field that takes the same filters and returns aggregates such as totalCount. Not every collection has one (exports, lists, scheduled exports, and transfers don't), so check the GraphiQL Docs explorer. When a statistics field exists, pass it the same filter as the collection to keep counts consistent.

Collection & single-record arguments

These are identical for every endpoint below:

Argument Type Applies to Description
params.filters FilterInput collection / statistics Logical filter tree (see Filtering).
params.limit Int collection Max records to return. Keep ≤ 100.
params.offset Int collection Records to skip (pagination).
id ID! single resolver The record's unique identifier.

Mutations

Create / update mutations take flat arguments (not a single wrapper) and return the affected object directly — there is no payload wrapper and no errors list. A create takes a required type enum (e.g. listType: ListTypeEnum!) plus a params input (e.g. ListInput!); an update additionally takes a top-level id: ID!. Inspect the exact input type and enum values in the GraphiQL Docs explorer.

mutation {
  createList(listType: ContactList, params: { /* fields from ListInput */ }) {
    id
    name
  }
}

Endpoints

🧭 Each operation below links to a prefilled GraphiQL query and includes a runnable cURL example. Fill in the prefilled Query Variables panel (replace REPLACE_ID, flesh out params) and adjust field selections as needed. Signatures use Numero's …Collection reads (some with a sibling …Statistics) and create… / update… mutations — verify exact input fields in the Docs explorer. For the full set of selectable fields on each endpoint, see the Platform API field reference.

contacts

Read, create, and update contact records.

bulkActions

Run a bulk action over a set of records (e.g. contacts, contributions). processBulkActions is asynchronous — it returns { accepted } to acknowledge the request, then processes in the background.

contributions

Read contribution records.

interactions

Read interaction (activity) records.

pledges

Read pledge records.

rsvps

Read RSVP records.