ICA UNIFIED / DEVELOPER GUIDE
Connect membership systems and registration forms to your Unified workspace. Each key belongs to one organization. Owners and admins manage keys and webhooks in Integrations.
Manage API keys and webhooks →curl 'https://unified.icomputeranything.com/api/v1/members' \ -H "Authorization: Bearer $ICA_API_KEY"
Use your existing Unified organization account. Only owners/admins can create keys in Integrations. Select the required permissions and expiry. Existing keys keep their member permissions; create a replacement with the new scopes when expanding an integration.
members:read, members:write, courses:read, courses:write, enrollments:read, enrollments:write, credentials:read, credits:read, events:read, events:write, registrations:read, registrations:write, attendance:write, applications:read, applications:write
| Request | Scope | Purpose |
|---|---|---|
GET /api/v1/courses | courses:read | List courses |
POST /api/v1/courses | courses:write | Create a course |
GET /api/v1/courses/{id}/lessons | courses:read | Read lessons without quiz answers |
POST /api/v1/courses/{id}/lessons | courses:write | Add a lesson or quiz |
GET /api/v1/enrollments | enrollments:read | Assignments, progress and completion |
POST /api/v1/enrollments | enrollments:write | Assign one active member to a course |
GET /api/v1/credentials | credentials:read | Issued credentials |
GET /api/v1/credits | credits:read | CE transcript entries |
GET /api/v1/events | events:read | Event workflows |
POST /api/v1/events | events:write | Create an event |
GET /api/v1/events/{id}/registrations | registrations:read | Registration and payment status |
POST /api/v1/events/{id}/registrations | registrations:write | Register or waitlist an attendee |
POST /api/v1/events/{id}/attendance | attendance:write | Record eligible member attendance |
GET /api/v1/applications | applications:read | Membership programs |
GET /api/v1/applications/{id}/submissions | applications:read | Application decisions and payment status |
POST /api/v1/applications/{id}/submissions | applications:write | Submit an application for a membership program |
List endpoints return data and nextCursor. Use ?limit=100 (1–100) and pass nextCursor as ?after=. Enrollments can filter by userId/courseId; credentials and credits can filter by userId. IDs and results always belong to the key’s organization. Member listing includes userId for learner assignments.
Every new POST endpoint above requires an Idempotency-Key of 8–100 letters, digits, underscores or hyphens. Reuse the same key and input when a response is lost. Receipts last 24 hours: new writes return 201, replay returns 200 with replayed=true; changed input returns 409. Database writes, the receipt and API webhook records commit together. JSON bodies are limited to 64 KiB; unknown fields return 400. No endpoint accepts a company ID to override the key’s organization.
{
"title": "Safety training",
"description": "Annual refresher",
"passingScore": 80,
"published": true
}POST this to /api/v1/courses; the response supplies id. Add lessons at /api/v1/courses/COURSE_ID/lessons with an explicit unique order:
{
"title": "Safety introduction",
"kind": "TEXT",
"content": "Read the safety instructions.",
"order": 1
}Lesson kinds: TEXT, VIDEO, DOCUMENT, QUIZ, LIVE. Optional mediaUrl must use HTTPS; LIVE requires it. QUIZ requires question, options (2–6) and correctAnswer matching an option. Read responses omit correct answers. Course fields also support durationMin, required and certificateValidDays. Assign with:
{
"courseId": "COURSE_ID",
"userId": "USER_ID",
"dueAt": "2026-12-31T23:59:59Z"
}POST assignments to /api/v1/enrollments. Members must be active. Reassignment updates dueAt without resetting progress or completion; omit dueAt to clear it. Learners complete lessons/quizzes in Unified. This API reads progress and issued credentials; it does not let integrations invent completion, passing scores or CE credits. Use course.completed and credential.issued webhooks, then retrieve the authoritative records.
{
"name": "Annual conference",
"status": "ACTIVE",
"startAt": "2026-12-01T12:00:00Z",
"capacity": 100,
"price": 0,
"ceuCredits": 2,
"creditCategory": "GENERAL",
"checkinMode": "BOTH",
"certificateRule": "ATTENDANCE"
}POST to /api/v1/events. The default status is DRAFT; use ACTIVE when ready. Optional endAt must follow startAt; meetingLink must use HTTPS. Price is in currency units and configures the existing workflow; API creation does not collect money or enable payments.
{
"name": "Example attendee",
"email": "attendee@example.com",
"phone": "",
"company": "Example company",
"notes": "Accessibility request"
}POST to /api/v1/events/EVENT_ID/registrations. Capacity assigns REGISTERED, WAITLISTED or PAYMENT_PENDING according to the workflow. Repeated workflow/email registration with a different request key returns 409. Staff review and checkout stay in the existing Unified workflow; the API cannot mark payments paid.
For attendance, POST {"userId":"USER_ID"} to /api/v1/events/EVENT_ID/attendance using attendance:write. The member must be active and have a REGISTERED submission; paid events require confirmed payment. Attendance awards only the event’s configured credits/certificate, once. Duplicate attendance does not issue another award. A scoped integration is an authorized attendance recorder; give this permission only to trusted staff systems.
GET /api/v1/applications to find membership program IDs created in Workflows. Submit the same name/email/contact fields to /api/v1/applications/PROGRAM_ID/submissions. The program must be active. GET that endpoint to check decisions/payment status. Approval rules and payment requirements remain enforced; the API cannot approve an application or activate a membership. Staff completes review/activation through Workflows, including already-approved free submissions.
| Request | Scope | Behavior |
|---|---|---|
| GET /api/v1/members | members:read | Returns up to 500 members of the key’s organization. |
| POST /api/v1/members | members:write | Creates an invitation. The person must accept it to activate membership. |
{
"name": "Example Member",
"email": "member@example.com",
"jobTitle": "Coordinator",
"role": "MEMBER"
}POST returns 201 with an invitation ID, activation URL, and expiry. Treat activation URLs as private. A duplicate organization membership returns 409. Invalid input returns 400; missing, revoked, or expired keys return 401; missing scopes return 403; inactive subscription access returns 402; rate limits return 429 with Retry-After. Respect the key’s configured request limit.
Add an HTTPS receiver in Integrations and copy its signing secret once. Select the events you need: member.invited, member.activated, migration.members.completed, event.registration.received, membership.application.received, workflow.submission.updated, course.created, course.assigned, course.completed, credential.issued, event.created, event.attendance.recorded, and membership.application.decided. Use Send test event to check delivery before relying on it.
Requests contain X-ICA-Event, X-ICA-Event-ID, and X-ICA-Signature. Verify the HMAC-SHA256 of the exact raw request body with your webhook secret and compare it in constant time against the hex value after sha256=. Decode JSON only after verification. Store event IDs to ignore duplicates.
{
"id": "event-id",
"event": "member.invited",
"createdAt": "ISO-8601 timestamp",
"data": {
"invitationId": "invitation-id"
}
}Return a 2xx response promptly. Delivery has an eight-second timeout and redirects are rejected. Events are saved before sending. Network errors, timeouts, HTTP 408/425/429 and 5xx responses are retried with increasing delays, up to eight attempts within 24 hours. A background worker checks due deliveries every five minutes. Other non-2xx responses stop delivery. Retries retain the same event ID and raw payload; delivery is at least once, so receivers must ignore IDs already processed. Removed or disabled endpoints are not retried. Integrations shows pending and failed delivery counts. Failed payloads are removed after seven days; successfully delivered payloads are cleared immediately. Reconcile records through the member API if delivery expires or permanently fails. These webhook secrets are separate from Stripe webhook credentials.
New API writes queue their notifications for the scheduled worker (normally checked within five minutes). Course completion and existing workflow actions also emit notifications. Treat each notification as a signal to retrieve current records; API and webhook credentials are separate. Application-decision events report the decision but do not grant payment or membership access.
The API follows your organization’s Unified subscription access. An API key does not grant access to another company or to ICA’s Stripe account. Additional endpoints and custom integrations require a separate scope agreement.