Public documentation for the Confanum Zapier integration. Covers OAuth 2.0 authentication, polling triggers, action endpoints, and the JSON shapes you can wire into Zaps.
Last updated 2026-05-16 · Production endpoint: https://api.confanum.com ·
Zapier integration: App241777
The Confanum Zapier integration uses the OAuth 2.0 authorization-code flow. When a user connects their Zapier account, Zapier opens a popup to Confanum's authorization endpoint. The user signs in with their existing Confanum admin account, picks the company whose data the Zap will see, and approves access. Confanum then issues an access token + refresh token, which Zapier uses to poll trigger endpoints (every 5–15 minutes) and call action endpoints when a Zap fires.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Zapier popup │───▶│ api.confanum.com │───▶│ Consent UI on │
│ │ │ /oauth/authorize │ 302│ admin.confanum │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
│ user signs in,
│ picks company,
│ clicks Authorize
▼
┌─────────────────┐ ┌──────────────────────────────────────┐
│ Zapier │◀───│ Redirect: code + state → Zapier's │
│ exchanges code │ │ /dashboard/auth/oauth/return/App… URL│
│ for access+ │ └──────────────────────────────────────┘
│ refresh tokens │
└─────────────────┘
│
│ Authorization: Bearer <access_token>
▼
┌─────────────────────────────────────────────┐
│ api.confanum.com/api/integrations/triggers │
│ api.confanum.com/api/integrations/actions │
└─────────────────────────────────────────────┘
All endpoints live on https://api.confanum.com — the same
production domain used by Confanum's admin platform and mobile apps. There is
no sandbox tier; the Zapier integration operates on real, live data, with
per-company tenant isolation enforced server-side.
Confanum implements RFC 6749 (authorization code) and RFC 7009 (revocation).
All OAuth endpoints are mounted under /oauth.
/oauth/authorizeBrowser entry point. Zapier redirects the user here. Confanum then
302-redirects to the consent UI on admin.confanum.com, which
handles sign-in + company selection. Query parameters (per RFC 6749):
| Param | Required | Notes |
|---|---|---|
response_type | yes | Must be code. |
client_id | yes | Issued by Confanum when the partner is provisioned. |
redirect_uri | yes | Must match a URI registered on the client's allow-list. |
scope | no | Space-separated. Defaults to the client's registered scopes (currently read_write). |
state | recommended | Opaque value echoed back on redirect. Used by Zapier (and you) for CSRF protection. |
On approval, the user's browser is redirected to:
<redirect_uri>?code=<64-hex code>&state=<state>
/oauth/tokenExchange an authorization code (or refresh token) for tokens. Use
application/json or application/x-www-form-urlencoded.
POST /oauth/token
Content-Type: application/json
{
"grant_type": "authorization_code",
"code": "<64-hex code from /authorize redirect>",
"redirect_uri": "https://zapier.com/dashboard/auth/oauth/return/App241777CLIAPI/",
"client_id": "<your client_id>",
"client_secret": "<your plaintext secret>"
}
POST /oauth/token
Content-Type: application/json
{
"grant_type": "refresh_token",
"refresh_token": "<64-hex refresh token>",
"client_id": "<your client_id>",
"client_secret": "<your plaintext secret>"
}
{
"access_token": "<64 hex chars>",
"refresh_token": "<64 hex chars>",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read_write"
}
/oauth/refreshConvenience alias for /token with grant_type=refresh_token.
Same body, minus the grant_type field.
/oauth/revokeRFC 7009 token revocation. Returns 200 even when the token isn't found (per spec).
POST /oauth/revoke
Content-Type: application/json
{
"token": "<access or refresh token to revoke>",
"client_id": "<your client_id>",
"client_secret": "<your plaintext secret>"
}
Response 200: { "revoked": true }
/api/integrations/meGET /api/integrations/me
Returns the company the bearer token is bound to plus the granted scopes. Zapier calls this after auth to label the connection, and as a cheap pre-flight on subsequent polls. Use it from your own integration as a connection-health check.
GET /api/integrations/me
Authorization: Bearer <access_token>
Response 200:
{
"company_id": "ba4ab352-c213-4f04-b809-94f7300bf7b2",
"company_name": "Acme Productions",
"company_short_name": "acme",
"scope": "read_write"
}
All trigger endpoints live under /api/integrations/triggers/.
Auth is Authorization: Bearer <access_token>. Each response is
a JSON array; Zapier dedupes by the row's id field. The
since query parameter accepts an ISO 8601 timestamp; rows older
than that are filtered out. Default since: 24 hours ago. Each
response is capped at 100 rows.
/api/integrations/triggers/new_orders?since=<ISO>One row per orders row created after since, scoped
to the OAuth-token's company.
[
{
"id": 10,
"order_number": "ACME-MP8WQ9RV",
"event_id": 104,
"event_name": "ACME Comic Fest",
"customer_first_name": "Bill",
"customer_last_name": "Watters",
"customer_email": "bill@example.com",
"customer_phone": "",
"total": "80.00",
"subtotal": "75.00",
"discount_amount": "0.00",
"service_fee": "5.00",
"fee_total": "5.00",
"addon_total": "0.00",
"tax_total": "0.00",
"refund_amount": "0.00",
"order_status": "complete",
"payment_status": "paid",
"payment_provider": "stripe",
"created_at": "2026-05-16T22:17:51.000Z",
"updated_at": "2026-05-16T22:17:51.000Z"
}
]
Currency fields are MySQL DECIMAL values returned as strings; Zapier
displays them as numbers in the editor. SQL filter: orders.created_at > :since.
/api/integrations/triggers/new_attendees?since=<ISO>One row per order_items row (i.e., per individual attendee).
A 4-ticket order produces 4 trigger rows. Dedup key: order_items.id.
[
{
"id": 10,
"order_id": 10,
"order_number": "ACME-MP8WQ9RV",
"ticket_type_id": 9,
"ticket_name": "Weekend Admission",
"badge_type": "general",
"event_id": 104,
"event_name": "ACME Comic Fest",
"attendee_first_name": "Bill",
"attendee_last_name": "Watters",
"attendee_email": "bill@example.com",
"seat_label": null,
"qr_code": "aa53a72561ec3906",
"checked_in": 0,
"checked_in_at": null,
"refunded": 0,
"unit_price": "75.00",
"total_price": "75.00",
"created_at": "2026-05-16T22:17:51.000Z",
"customer_first_name": "Bill",
"customer_last_name": "Watters",
"customer_email": "bill@example.com",
"customer_phone": ""
}
]
/api/integrations/triggers/schedule_changes?event_id=<id>&since=<ISO>Returns all schedule items for the given event. event_id is
required and validated against the OAuth-token's company. Dedup key: id.
schedule table doesn't yet
have an updated_at column, so we can't filter by
since — the endpoint returns all rows for the event and
relies on Zapier's id-based dedupe. New items trigger correctly; edits to
existing items do not trigger. We expect to add
updated_at in a near-term schema update.
[
{
"id": 442,
"event": "Cosplay Contest",
"description": "Costume parade + awards",
"date": "2026-05-30",
"time": "14:00:00",
"end_date": "2026-05-30",
"end_time": "16:00:00",
"start_at": "2026-05-30T14:00:00",
"end_at": "2026-05-30T16:00:00",
"location": "Main Stage",
"tags": "[\"cosplay\",\"family\"]",
"guests": "[]",
"eventId": 104,
"hide": 0,
"paid": 0,
"track": null
}
]
start_at and end_at are ISO 8601 timestamps
synthesized from the underlying date + time /
end_date + end_time columns. Times are the event's
local time; no timezone designator is appended since the schedule table
doesn't yet store one.
/api/integrations/triggers/application_submissions?since=<ISO>Combined feed of vendor applications + panel submissions. Each row has a
kind field ("vendor" or "panel") so
filters can branch in the Zap. The id is a synthetic composite
(vendor-42, panel-7) so the two row types stay
distinct for Zapier's dedup.
[
{
"id": "vendor-42",
"kind": "vendor",
"application_id": 42,
"event_id": 104,
"event_name": "ACME Comic Fest",
"vendor_id": 18,
"vendor_name": "Astro Comics & Collectibles",
"vendor_email": "hello@astrocomics.example",
"status": "submitted",
"booth_type": "10x10",
"product_description": "Independent comics + back-issue boxes",
"created_at": "2026-05-15T18:42:00.000Z"
},
{
"id": "panel-7",
"kind": "panel",
"application_id": 7,
"event_id": 104,
"event_name": "ACME Comic Fest",
"vendor_id": null,
"vendor_name": "Jane Doe",
"vendor_email": "jane@example.com",
"panel_title": "Inking Demo: Brush vs Nib",
"panel_type": "demo",
"status": "submitted",
"created_at": "2026-05-15T19:08:00.000Z"
}
]
/api/integrations/triggers/eventsHelper endpoint that powers event-picker dropdowns in the Zap editor. Returns the company's 100 most-recent events.
[
{ "id": 104, "name": "ACME Comic Fest", "start_date": "2026-05-29", "end_date": "2026-05-30" },
{ "id": 103, "name": "Pensacola Con 2026", "start_date": "2026-08-15", "end_date": "2026-08-17" }
]
All action endpoints live under /api/integrations/actions/.
Same OAuth bearer auth. Content-Type: application/json.
| Action | Endpoint | Status |
|---|---|---|
| Send Email | POST /api/integrations/actions/send_email | Wired, full implementation rolling out incrementally |
| Add To Segment | POST /api/integrations/actions/add_to_segment | Wired, full implementation rolling out incrementally |
| Post Message | POST /api/integrations/actions/create_message | Wired, full implementation rolling out incrementally |
| Register Attendee | POST /api/integrations/actions/register_attendee | Hidden in Zapier UI during beta; contact us for access |
POST /api/integrations/actions/send_email
Authorization: Bearer <access_token>
Content-Type: application/json
{
"to": "attendee@example.com",
"subject": "Your tickets for ACME Comic Fest",
"body": "Plain-text body or HTML.",
"event_id": 104
}
Response 200: { "sent": true, "message_id": "<provider message id>" }
POST /api/integrations/actions/add_to_segment
{
"email": "fan@example.com",
"segment_name": "Newsletter",
"first_name": "Jane",
"last_name": "Doe"
}
Response 200: { "added": true, "contact_id": 4242, "segment_name": "Newsletter" }
segment_name is free text; the segment is auto-created if it doesn't exist.
POST /api/integrations/actions/create_message
{
"event_id": 104,
"title": "Doors open at 10am",
"body": "First sessions begin at 10:30. See you there!",
"type": "announcement"
}
Response 200: { "message_id": 999, "event_id": 104, "created_at": "2026-05-16T19:30:00.000Z" }
type is one of announcement, alert,
info — drives the icon + styling on attendee devices.
Programmatic ticket creation for syncing comp or external registrations.
POST /api/integrations/actions/register_attendee
{
"event_id": 104,
"ticket_type_id": 9,
"attendee_email": "fan@example.com",
"attendee_name": "Jane Doe",
"mark_as_paid": true
}
Hidden in the Zapier UI until the underlying ticket service supports the full comp / mark-as-paid path. Contact us for early access if you need this for a beta rollout.
Standard HTTP status codes. Error bodies look like:
{
"error": "invalid_grant",
"message": "Authorization code is invalid, expired, or already used"
}
Common codes:
invalid_request, invalid_grant, unsupported_response_type, unsupported_grant_typeguid.# 1. Open in a browser while signed into admin.confanum.com (or a fresh window
# where you'll sign in):
#
# https://api.confanum.com/oauth/authorize?response_type=code&client_id=<your_id>&redirect_uri=https://example.com/cb&scope=read_write&state=test
#
# Approve → browser redirects to example.com/cb?code=<64-hex>
CODE=<paste the code here>
CLIENT_ID=<your client_id>
CLIENT_SECRET=<your client_secret>
# 2. Exchange code for tokens.
TOKENS=$(curl -s -X POST https://api.confanum.com/oauth/token \
-H "Content-Type: application/json" \
-d "{\"grant_type\":\"authorization_code\",\"code\":\"$CODE\",\"redirect_uri\":\"https://example.com/cb\",\"client_id\":\"$CLIENT_ID\",\"client_secret\":\"$CLIENT_SECRET\"}")
echo "$TOKENS"
ACCESS_TOKEN=$(echo "$TOKENS" | jq -r .access_token)
# 3. Confirm /me.
curl -s https://api.confanum.com/api/integrations/me \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq
# 4. Poll a trigger.
curl -s "https://api.confanum.com/api/integrations/triggers/new_orders?since=2026-05-01T00:00:00Z" \
-H "Authorization: Bearer $ACCESS_TOKEN" | jq
# 5. Refresh.
REFRESH=$(echo "$TOKENS" | jq -r .refresh_token)
curl -s -X POST https://api.confanum.com/oauth/token \
-H "Content-Type: application/json" \
-d "{\"grant_type\":\"refresh_token\",\"refresh_token\":\"$REFRESH\",\"client_id\":\"$CLIENT_ID\",\"client_secret\":\"$CLIENT_SECRET\"}" | jq
For native partner credentials (your own client_id /
client_secret) or implementation assistance:
https://api.confanum.comLooking for the Zapier app itself? Search "Confanum" in the Zapier editor when creating a Zap. As of 2026-05-16, the integration is in invite-only beta — once it ships in the public Zap directory we will update this page with a direct link.