Integrations · Zapier

Zapier Integration API Reference

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

1. Overview & architecture

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.

2. Authentication — OAuth 2.0

Confanum implements RFC 6749 (authorization code) and RFC 7009 (revocation). All OAuth endpoints are mounted under /oauth.

2.1 GET /oauth/authorize

Browser 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):

ParamRequiredNotes
response_typeyesMust be code.
client_idyesIssued by Confanum when the partner is provisioned.
redirect_uriyesMust match a URI registered on the client's allow-list.
scopenoSpace-separated. Defaults to the client's registered scopes (currently read_write).
staterecommendedOpaque 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>

2.2 POST /oauth/token

Exchange an authorization code (or refresh token) for tokens. Use application/json or application/x-www-form-urlencoded.

Authorization-code grant

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>"
}

Refresh-token grant

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>"
}

Response (both grants)

{
  "access_token":  "<64 hex chars>",
  "refresh_token": "<64 hex chars>",
  "token_type":    "Bearer",
  "expires_in":    3600,
  "scope":         "read_write"
}

2.3 POST /oauth/refresh

Convenience alias for /token with grant_type=refresh_token. Same body, minus the grant_type field.

2.4 POST /oauth/revoke

RFC 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 }

3. Authentication test — /api/integrations/me

GET /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"
}

4. Triggers — Zapier polls these

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.

4.1 GET /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.

4.2 GET /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":       ""
  }
]

4.3 GET /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.

Limitation: the 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.

4.4 GET /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"
  }
]

4.5 GET /api/integrations/triggers/events

Helper 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" }
]

5. Actions — Zapier calls these when a Zap fires

All action endpoints live under /api/integrations/actions/. Same OAuth bearer auth. Content-Type: application/json.

ActionEndpointStatus
Send EmailPOST /api/integrations/actions/send_emailWired, full implementation rolling out incrementally
Add To SegmentPOST /api/integrations/actions/add_to_segmentWired, full implementation rolling out incrementally
Post MessagePOST /api/integrations/actions/create_messageWired, full implementation rolling out incrementally
Register AttendeePOST /api/integrations/actions/register_attendeeHidden in Zapier UI during beta; contact us for access

5.1 Send Email

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>" }

5.2 Add Contact to Segment

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.

5.3 Post In-App Message

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.

5.4 Register Attendee (hidden during beta)

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.

6. Rate limits, errors, and security

Rate limits

Errors

Standard HTTP status codes. Error bodies look like:

{
  "error":   "invalid_grant",
  "message": "Authorization code is invalid, expired, or already used"
}

Common codes:

Security

7. Test recipes (curl)

End-to-end smoke test

# 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

8. Contact & partner access

For native partner credentials (your own client_id / client_secret) or implementation assistance:

Looking 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.