The basics
The API is a versioned REST surface over HTTPS. All requests are tenant-scoped: the credential you authenticate with determines which organization's data you see, and nothing in a request body, path, or query string can widen that.
| Base URL | https://api.ebixcoi.com |
|---|---|
| Version prefix | /v1 (in every path) |
| Format | JSON request and response bodies; multipart for document upload |
| Errors | RFC 7807 application/problem+json with stable string codes |
| Calling context | Server-to-server only. No browser CORS is offered in this phase. |
Authentication
Two credential types are supported. Both are minted by your administrator in the ebixcoi web app under Admin > System & Governance > API & Integrations.
1. API keys (simplest)
A long-lived bearer secret with read and/or write scopes. Keys look like ebx_ followed by 44 hex characters and are shown once at creation.
curl https://api.ebixcoi.com/v1/insureds \
-H "Authorization: Bearer ebx_YOUR_KEY"
2. OAuth 2.0 client credentials
For organizations that prefer short-lived credentials. Your admin creates an OAuth client (a ebxc_... client ID and a one-time ebxs_... client secret). Exchange them for a bearer access token valid for 1 hour:
curl -X POST https://api.ebixcoi.com/v1/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=client_credentials \
-d client_id=ebxc_YOUR_CLIENT_ID \
-d client_secret=ebxs_YOUR_CLIENT_SECRET
{"access_token":"ebxo_...","token_type":"Bearer","expires_in":3600,"scope":"read write"}
Then call any endpoint with Authorization: Bearer ebxo_... exactly as you would with an API key. HTTP Basic authentication and a JSON request body are also accepted on the token endpoint. An optional scope parameter (space-delimited) requests a subset of the client's allowed scopes.
read; POST, PATCH, and DELETE require write. A credential without the needed scope receives 403 forbidden.Onboarding workflow (order of operations)
Your tenant is configured by an Ebix onboarding manager before API work starts: company settings and the standard risk profiles already exist. The integration flow is:
| Step | Call | Purpose |
|---|---|---|
| 1 | GET /v1/risk-profiles | Discover the pre-configured risk (insurance) profiles and capture the UUID to associate. Risk profiles are read-only via the API. |
| 2 | POST /v1/business-units | Create (or GET to list) the organizational units insureds belong to. |
| 3 | POST /v1/insureds | Create the vendor/insured with insurance_profile_id and business_unit_id set. Bulk: POST /v1/insureds/bulk (up to 500 rows, per-row outcomes). |
| 4 | POST /v1/insureds/{id}/coi-documents | Upload the certificate of insurance (multipart, 15 MB max). Processing is asynchronous: you get 201 immediately and the document moves to review as extraction completes. |
| 5 | GET /v1/insureds/{id}/compliance | Read compliance status, deficiencies, and scoring once evaluation runs. |
Example: create an insured
curl -X POST https://api.ebixcoi.com/v1/insureds \
-H "Authorization: Bearer ebx_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed" \
-d '{
"name": "Acme Mechanical LLC",
"external_id": "VEND-88421",
"insurance_profile_id": "RISK_PROFILE_UUID",
"business_unit_id": "BUSINESS_UNIT_UUID",
"contact_email": "coi@acmemech.example"
}'
Example: upload a COI
curl -X POST https://api.ebixcoi.com/v1/insureds/INSURED_UUID/coi-documents \
-H "Authorization: Bearer ebx_YOUR_KEY" \
-F "file=@certificate.pdf"
Conventions you should build against
Errors
Every error is an RFC 7807 problem document with a stable code:
{
"type": "https://developers.ebixcoi.com/errors/validation_error",
"title": "Validation Error",
"status": 422,
"code": "validation_error",
"detail": "internal_id not found in tenant",
"request_id": "..."
}
Common codes: unauthorized (401), forbidden (403), not_found (404), conflict / idempotency_conflict (409), validation_error (422), rate_limited (429). The single exception is the OAuth token endpoint, which follows the OAuth 2.0 standard error format ({"error": "invalid_client", ...}) for interoperability.
Pagination
List endpoints return {"data": [...], "next_cursor": "..."}. Pass ?cursor= to fetch the next page. Default page size 50, maximum 500 via ?limit=. Cursors are opaque; do not parse them.
Rate limits
600 requests/minute and 10,000 requests/hour per organization, with a per-credential hourly ceiling. Every authenticated response carries X-RateLimit-Limit-Hour, X-RateLimit-Remaining-Hour, and X-RateLimit-Reset; a 429 includes Retry-After.
Idempotency
Send an Idempotency-Key header (any UUID) on writes. Replaying the same key with the same body within 24 hours returns the original response; the same key with a different body returns 409 idempotency_conflict. The multipart document upload does not honor idempotency keys; design retries around the returned document id instead.
Deletes are archives
DELETE on business resources (insureds, business units, documents) archives the record; nothing is destroyed and history remains queryable in the ebixcoi app. Integration configuration (external ID mappings) is likewise soft-deleted and the same external identifier can be re-registered afterwards.
Request tracing
Every response carries an X-Request-Id. Log it; quote it in support requests. Your administrators can see the same id in the Request Log inside the ebixcoi app.
External ID mappings
If your system has its own identifiers for vendors, register them so future syncs can address records by your IDs:
curl -X POST https://api.ebixcoi.com/v1/external-mappings \
-H "Authorization: Bearer ebx_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"system": "yourerp",
"external_kind": "vendor",
"external_id": "VEND-88421",
"internal_kind": "insured",
"internal_id": "INSURED_UUID"
}'
Bulk registration: POST /v1/external-mappings/bulk (up to 500 rows).
Webhooks
Register HTTPS endpoints (POST /v1/webhooks/subscriptions or via the admin UI) to be notified when things happen in ebixcoi, instead of polling. A subscription carries one or more event filters: either a whole category (compliance.*) or a single event (compliance.became_noncompliant). Each subscription receives a one-time signing secret (whsec_...) used to verify that deliveries genuinely came from ebixcoi.
Available events
| Filter | Event | Fires when |
|---|---|---|
insured.*Insureds: vendor and insured lifecycle |
insured.created | A new insured is added (app, API, bulk import, or integration) |
insured.updated | An insured's profile details change | |
insured.archived | An insured is archived | |
coi_document.*COI Documents: certificate processing pipeline |
coi_document.uploaded | A new certificate is received (API, portal, or email intake) |
coi_document.extraction_completed | AI extraction finishes and the document enters the review queue | |
coi_document.extraction_failed | Extraction fails and the document needs attention | |
coi_document.approved | A reviewer approves the document; its coverages become active evidence | |
coi_document.archived | A document is archived | |
compliance.*Compliance: evaluation outcomes |
compliance.evaluated | A compliance evaluation completes for an insured |
compliance.became_compliant | An insured transitions to compliant | |
compliance.became_noncompliant | An insured transitions to non-compliant (new deficiencies) | |
policy.*Policies: coverage and expiration lifecycle |
policy.activated | An approved coverage version becomes active evidence |
policy.expiring_soon | A policy is approaching its expiration date | |
policy.expired | A policy passes its expiration date | |
integration.*Integrations: connected-system sync health |
integration.sync_completed | An integration sync run finishes |
integration.sync_failed | An integration sync run fails | |
external_mapping.*External ID Mappings: identifier registry changes |
external_mapping.created | An external ID mapping is registered |
external_mapping.deleted | An external ID mapping is removed |
Wildcard filters (category.*) are recommended: your endpoint automatically receives any new events added to that category later. Subscriptions can be paused, resumed, and revoked at any time via the API or the admin UI.
Full reference
Every endpoint, schema, parameter, and error is documented in the complete API reference (OpenAPI 3.1).
Support
Questions or unexpected responses: contact your Ebix RCS service consultant and include the X-Request-Id of the affected call.