Many organizations consolidate Administrate data into a data warehouse or Business Intelligence platform (Microsoft Fabric, Power BI, Snowflake, Looker and similar) alongside data from other systems. Administrate does have packaged connectors available to many of these platforms through the Administrate Automator product.
You can also connect to Business Intelligence systems without using Automator by combining these building blocks:
- GraphQL APIs — pull data on your schedule, with filters that make incremental extraction efficient.
- Webhooks — have Administrate push change notifications to your pipeline as records change.
- Report exports — point-in-time CSV/Excel snapshots for ad-hoc needs, not pipelines.
This guide describes the patterns that work well and the limits to design around. For API access itself, start with the Developer Portal.
The overall pattern
A typical warehouse feed uses two phases:
- Initial backfill — page through each entity with the GraphQL API and load everything once.
- Ongoing sync — either scheduled incremental pulls (filter each entity on its last-updated time), webhooks pushing changes as they happen, or both: webhooks for freshness, plus a nightly incremental sweep as a safety net.
Initial backfill
Query each entity as a paginated connection. Pages return up to 100 records (the default is 50); use pageInfo for the total and offset to walk the set:
{
events(filters: [], first: 100, offset: 0) {
pageInfo { totalRecords }
edges {
node {
id
title
start
end
lifecycleState
}
}
}
}
The core entities most warehouse feeds extract: Accounts, Contacts, Course Templates, Events, Sessions, Registrations, Learners (one per learner per event — usually your fact-table grain), Learning Paths, and the financial documents (Invoices, Credit Notes, Payments).
Respect the API rate limit of 6,000 requests per 5 minutes per IP address. At 100 records per request that is comfortably enough for full corpus backfills, but batch your workers rather than parallelizing aggressively.
Incremental pulls
Most core entities support filtering on a last-updated timestamp with ge (greater-than-or-equal) comparisons, so a scheduled job should only fetch what changed since its last run:
{
learners(
filters: [{ field: lastUpdatedAt, operation: ge, value: "2026-07-30T00:00:00" }]
first: 100
) {
edges { node { id lastUpdatedAt } }
}
}
One naming quirk to know: Events filter on updatedAt, while Accounts, Contacts, Learners, Registrations and Learning Paths filter on lastUpdatedAt.
Financial documents are dated on the documents themselves, and do not support update-time filtering — sync them through the finance webhooks below, and we suggest that you only sync "finalized" invoices in order to avoid pulling in-progress data.
Store your high-water mark (the largest timestamp you have processed) per entity, and overlap each run slightly rather than using strict greater-than, so records updated during a run are not missed.
Webhooks as the change feed
Webhooks push changes to your endpoint as they happen. Two properties make them well suited to warehouse pipelines:
- You define the payload as a GraphQL query, so a webhook can deliver exactly the columns your pipeline needs — no second lookup required.
- Coverage is broad: event and session lifecycle (
Event Created/Updated/Published/Cancelled, session created/updated/deleted), learner lifecycle (registered, cancelled, transferred, attended/missed session, passed/failed, results issued and updated), account and contact updates, course template publishes, learning path progress, and the financial documents —InvoiceFinalised,CreditNoteCreated,CreditNoteFinalised,ReceiptCreated,RefundCreated,PurchaseOrderCreated(quoted as named in the product, which uses the British spelling). QuerywebhookTypesin the API to discover the full current list.
Design your consumer around the delivery guarantees:
- Failed deliveries (HTTP 5xx or 429) are retried three times, at 30 seconds, 1 minute and 2 minutes; 4xx responses are not retried.
- A webhook that fails 100 consecutive times within 24 hours is automatically deactivated, with an email to its configured notification addresses — monitor for that email, and check delivery history in Webhook Logs.
- Verify payloads with the shared-secret HMAC signature.
- Webhook execution is throttled at 200 per second, 2,000 per 5 minutes and 10,000 per hour — bulk operations (large imports, bulk event updates) can burst; make your endpoint fast and queue the processing.
Because retries are finite, treat webhooks as the freshness layer, not the source of truth: pair them with a periodic incremental pull so anything missed during an outage is repaired automatically.
Use filtered webhooks (a JMESPath expression on the payload) to limit deliveries to the records your pipeline cares about.
Keying records across systems
Use the GraphQL id as your natural key — it is stable and unique per record. If your warehouse or other systems have their own identifiers for the same records, Administrate's External IDs feature lets you store those foreign keys on the Administrate side, which simplifies cross-system joins and reconciliation; see the External IDs section of the Developer Portal.
Where report exports fit
The Reporting Engine's CSV/Excel exports are point-in-time snapshots — good for ad-hoc analysis and for validating your pipeline (the reporting entities define useful elements — Events: one row per delivery; Delegates: one row per learner registration). A report can also be emailed on a schedule as an attachment via a Scheduled communication trigger. Neither is a substitute for the API in an automated pipeline: exports are manual or email-borne, and not designed for machine consumption.
What to avoid
- Don't poll everything on a timer. Full re-pulls burn rate limit for data that hasn't changed; use the incremental filters and webhooks.
- Don't scrape report screens or parse emailed exports in a pipeline; the API is the supported machine interface.
- Don't treat webhook delivery as guaranteed. Retries are finite — reconcile with incremental pulls.