If you have ever worked in commercial insurance, you know ACORD 25. It is the Certificate of Liability Insurance. It is the one your customer needs because the property manager will not give them keys, or the GC will not let them on site, or the city will not issue the permit. They need it today.
Some brokers issue forty of these a day. Some agencies issue four hundred. The form has not changed materially since 2016, the data on it is sitting in your AMS, and yet someone is still printing them one by one.
This post walks through what it looks like to generate ACORD 25 certificates from a single API call. We will cover the fields, the common variants, additional insureds, and what to do about endorsements.
What is on the form
ACORD 25 is a one-page certificate that tells a third party (the "certificate holder") that a named insured has coverage in force. It is not a contract. It is informational only, which the form itself says in bold at the top. The third party reads it because they need proof that if your insured drops a forklift on their loading dock, somebody pays.
The fields fall into five blocks:
- Producer block (top left). Your agency name, address, contact name, phone, email.
- Insured block. The named insured and address.
- Insurers block (top right). The carriers providing each coverage, plus their NAIC number.
- Coverage rows. General Liability, Auto, Umbrella, Workers Comp, plus optional rows. Each row has policy number, effective date, expiration date, and limits.
- Certificate holder and description of operations (bottom). Often the most fragile box on the form, because it is free text and gets parsed by every COI tracking system in the country.
Why teams still issue these by hand
Almost every agency has a COI process. Most of them look like this:
- Customer or third party emails the request.
- Account manager looks up the policy in the AMS (Applied Epic, AMS360, HawkSoft, EZLynx, Nexsure).
- Account manager opens the AMS template editor, fills in certificate holder, description of operations, additional insured wording if needed.
- AMS generates the PDF. Account manager downloads it, attaches to email, sends.
It works. It also takes five to ten minutes per certificate when the system is slow, and the third party often comes back to ask for a different "additional insured" line, which is another round trip.
Every account manager has a story about issuing the same COI three times in a week because the GC keeps changing how they want their company name spelled.
What an API-driven flow looks like
Start with the ACORD 25 PDF. You can download it from acord.org once and upload it to Mezdoc as a structured template. Drop fields on the locations that correspond to the form blocks above. Each field gets an alias.
Publish v1 to production. Then every COI request becomes one HTTP call:
curl https://api.mezdoc.com/v1/templates/acord_25_v1/submissions \
-H "Authorization: Bearer $MEZDOC_KEY" \
-H "Idempotency-Key: coi_2026_05_19_00481" \
-d '{
"environment": "production",
"data": {
"producer_name": "Acme Insurance Services",
"producer_address": "200 Market St, San Francisco CA 94105",
"producer_contact": "Linda Park",
"producer_phone": "415-555-0142",
"producer_email": "linda@acme-ins.com",
"insured_name": "Bayside Logistics LLC",
"insured_address": "44 Pier 70, San Francisco CA 94107",
"carrier_gl_name": "Hartford Casualty Insurance Co",
"carrier_gl_naic": "29424",
"gl_policy": "GLP-2026-44102",
"gl_effective": "2026-04-01",
"gl_expiration": "2027-04-01",
"gl_occurrence": 2000000,
"gl_aggregate": 4000000,
"cert_holder_name": "Pier 70 Property LLC",
"cert_holder_addr": "44 Pier 70, San Francisco CA 94107",
"description": "Pier 70 Property LLC is named as Additional Insured per CG 20 10 04 13."
}
}'Response is an idempotent submission id. A webhook fires with a signed download URL within a second or two. Your AMS or your CRM stores the URL on the policy record.
Additional insureds and the description box
The Description of Operations / Locations / Vehicles box is where 80% of COI re-issues come from. The third party wants to be named as Additional Insured. They want the contract number on the certificate. They want a waiver of subrogation called out. They want the exact endorsement form number (CG 20 10, CG 20 37, etc).
Two patterns work well here:
Pattern A: structured description fields
Define separate fields for the common parts. additional_insured_name, endorsement_forms (an array), contract_reference, waiver_of_subrogation (boolean). Use a dynamic template fragment to compose the description text from these fields, instead of a free-form string.
Pros: every COI carries the same wording style. Re-issues are a one-field change.
Cons: account managers occasionally need to override the auto-generated text. So expose a raw description_override field that, if present, replaces the composed string.
Pattern B: raw description field
Keep one descriptionstring. Let the account manager type whatever the third party asked for. The flexibility helps. The downside is no consistency across certificates - one COI says "Additional Insured per CG 20 10 04 13", another says "AI per attached endorsement", which the third party's tracking system reads as different things.
Most agencies start with Pattern B because it is faster to set up, then move to Pattern A once they realise they keep issuing the same five wordings.
Handling endorsement schedules
Some certificate holders want a copy of the actual endorsement form attached to the COI. CG 20 10 04 13 is a one-page PDF. You can:
- Keep each endorsement form as a separate template in Mezdoc.
- Build a workflow that bundles the COI plus the endorsements the customer requested.
- Return a merged PDF: page 1 is the COI, pages 2 onward are the endorsements.
The customer gets a single packet. The third party stops emailing back to ask for the endorsement copy.
What it costs
Generating a certificate at this volume is essentially free in compute. The cost is the engineering time to wire the AMS to the API, which is one afternoon for most teams that already have a basic AMS export. After that the marginal cost per certificate is the cost of the API call, which is pennies.
The savings show up in three numbers your COO already tracks:
- Average time to issue a COI. Drops from minutes to seconds.
- Number of COI re-issues. Drops because the data is taken from one source and the description box is composed, not freehand.
- Time account managers spend on certificates. Drops, often by 60 to 80 percent for high-volume books.
One question that always comes up
Is the API-generated COI going to be accepted by the third party? Yes. ACORD 25 is a public form. The bytes the API emits are the same bytes you would have produced by hand. The signature line is signed electronically with an audit trail (IP, UA, SHA-256 of the rendered PDF). Most third parties accept that without a second look. The ones that do not, do not accept your AMS-generated COIs either.
Start with the books that produce the most certificate volume. The big GCs, the master service agreements that require monthly proof, the city contracts. Wire those first. Everything else comes online once your account managers see the rhythm.
The India parallel
Indian commercial brokers have their own version of this problem. There is no national ACORD equivalent in India, but every general insurer (Tata AIG, ICICI Lombard, HDFC Ergo, Bajaj Allianz) publishes their own commercial COI format. The fields are recognisably the same: insured legal entity, GSTIN, policy number, sum insured, perils covered, additional insured for contracts that require it. Indian teams hit the same wall at scale: ops staff filling the same fields across multiple insurers, copy-pasting the same insured details, version drift when the insurer updates the COI format mid-year. The same Mezdoc template engine carries this with one workflow and a per-insurer template version pin.
Same template. Your code or your customer can fill it. The audit trail records both.
Open the full demoAutomating motor insurance proposal forms with one API
Indian brokers fill the same fifteen fields on the same proposal form thousands of times a month. Here is the API call that ends the typing.
IRDAI claim form A and B without the back-and-forth
Form A is the insured. Form B is the hospital. Together they cause more email chains than any other document in Indian health insurance. Here is how to automate them.