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].
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.
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. |
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
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.
These patterns are shared across every endpoint, so they're documented once here and not repeated for each one.
params wrapperList (collection) and statistics fields take a single params argument that wraps filters and pagination, e.g. listsCollection(params: $dataParams).
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" } } }
]
}
}
_ltRelative / _gtRelative with { quantity, direction: "ago", unit: "day" | "week" | "month" | ... }._eq, _neq, _gt, _gte, _lt, _lte, _in) are typically available, but the exact set is field-type dependent — confirm available operators per field in the GraphiQL Docs explorer.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.
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.
totalCountSome 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.
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. |
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
}
}
🧭 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 outparams) and adjust field selections as needed. Signatures use Numero's…Collectionreads (some with a sibling…Statistics) andcreate…/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.
Read, create, and update contact records.
contactsCollection(params: ContactsCollectionInput) — list contacts (+ contactsStatistics for totalCount). → Open in GraphiQL ▸
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 { contactsCollection(params: {limit: 10}) { contacts { id } } }"}'
contact(id: ID!) — fetch a single contact. → Open in GraphiQL ▸
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 { contact(id: \"REPLACE_ID\") { id } }"}'
createContact(params: ContactInput!) — create a contact. → Open in GraphiQL ▸
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":"mutation { createContact(params: {}) { id } }"}'
updateContact(id: ID!, params: ContactInput!) — update a contact (id required). → Open in GraphiQL ▸
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":"mutation { updateContact(id: \"REPLACE_ID\", params: {}) { id } }"}'
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.
processBulkActions(params: BulkActionsInput!, resource: BulkActionResourceEnum!) — run bulk actions over a resource. → Open in GraphiQL ▸
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":"mutation { processBulkActions(resource: Contact, params: {}) { accepted } }"}'
Read contribution records.
contributionsCollection(params: ContributionsCollectionInput) — list contributions (+ contributionsStatistics). → Open in GraphiQL ▸
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 { contributionsCollection(params: {limit: 10}) { contributions { id } } }"}'
contribution(id: ID!) — fetch a single contribution. → Open in GraphiQL ▸
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 { contribution(id: \"REPLACE_ID\") { id } }"}'
Read interaction (activity) records.
interactionsCollection(params: InteractionsCollectionInput) — list interactions (+ interactionsStatistics). → Open in GraphiQL ▸
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 { interactionsCollection(params: {limit: 10}) { interactions { id } } }"}'
interaction(id: ID!) — fetch a single interaction. → Open in GraphiQL ▸
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 { interaction(id: \"REPLACE_ID\") { id } }"}'
Read pledge records.
pledgesCollection(params: PledgesCollectionInput) — list pledges (+ pledgesStatistics). → Open in GraphiQL ▸pledge(id: ID!) — fetch a single pledge. → Open in GraphiQL ▸Read RSVP records.