Introduction
curl "https://api.mbctestweb.com/v1/obligations?state=IA" \
-H 'API_KEY: keykeykey'
Every response includes a
successflag:
{
"success": true,
"obligations": [
{
"id": 12345,
"state": "IA",
"name": "PRE-EXECUTED $10,000 Notary Public Bond",
"license_plate": "PNOTR",
"bond_amounts": [10000],
"term_length": 4,
"hub_express_enabled": true
}
]
}
Merchants Bonding API
The Merchants Bonding API is a RESTful, JSON-based API that lets your software write and service surety bonds directly with Merchants Bonding Company. It supports the full commercial bond lifecycle — quoting, ordering, issuing, documents, corrections, endorsements, cancellations and reinstatements — plus contract account submissions through the RAP program.
The API is agency-centric. Your API key belongs to exactly one agency, and every request operates on behalf of that agency. You never send an agency identifier: we resolve it from your key and scope what you can see and do accordingly.
Everything you do is real time and transparent. A bond you issue over the API exists the moment the call returns, and it appears in the Merchants Bonding Hub alongside bonds written any other way. Your team, your agency's staff, and Merchants underwriters all see the same bond, the same documents, and the same status.
Write your first bond →Browse the API reference →
Ready to write a bond now? The Quickstart takes five calls. If you want to understand the model first, read on.
What you can do
| Capability | What it covers | Reference |
|---|---|---|
| Bond form metadata | Look up the bond forms (obligations) your agency can write, by state, along with valid bond amounts, term lengths, required fields, and pricing | Obligations |
| Quoting | Price a bond and get an underwriting decision without issuing it. Quotes stay valid for 60 days and can be edited | Quotes |
| Ordering and issuing | Create a bond, either issuing immediately in one call or issuing later from an approved quote | Orders |
| Bond documents | Retrieve the executed bond form, application, invoice, and power of attorney as PDFs | Orders |
| Correcting and endorsing | Fix data-entry mistakes on a recent bond, or endorse an in-force bond and receive the resulting endorsement documents | Commercial Bonds |
| Canceling and reinstating | Cancel flat or pro-rata, non-renew at expiration, or reverse a cancellation | Commercial Bonds |
| Renewals | List upcoming renewals and update them before they process | Commercial Bonds |
| Contract account submissions | Submit a new contractor or developer account to the RAP program and track the underwriting decision | Account Submissions |
| Work in progress reporting | Submit WIP statements for contract accounts | Contract Bonds |
What you can build
A self-service bond storefront. For instant-issue forms such as notary bonds, a customer can pick a bond, pay, and download an executed PDF without anyone at your agency touching the order. Quoting, issuing, and document retrieval are three calls.
Bond ordering inside your agency management system. Keep your producers in one system. Look up the right obligation for the state and bond type, submit the order with the principal data you already have, and store the returned documents against your own record.
Automated servicing. Watch for renewals, push address and name changes as endorsements, and cancel for non-payment — all without email or phone calls to Merchants.
Contractor onboarding for RAP. Collect the account, owner, and indemnity information once and submit it as an account submission instead of rekeying a paper application.
Compliance and licensing platforms. Use the obligations catalog to show a licensee exactly which bond form and amount their state requires, then order it in place.
Core concepts
Obligation
An obligation is a specific bond form for a state and bond amount combination — for example, a $10,000 Iowa notary bond. Obligations are the catalog you order from, and every order references an obligation_id.
Fetching a single obligation tells you everything you need to build a valid order: which bond_amounts and years_increments are allowed, which standard_fields and form_specific_fields the form requires, whether it can_renew, whether it needs a wet signature, and the price_quotes for instant-issue forms. It also carries the underwriting rules described in Obligations.
Obligations also have a license plate — a short internal code such as PNOTR — that you may pass instead of, or alongside, the id.
Order and quote
An order is a request to create a bond. Orders and quotes take the same information about the principal and the bond form; the difference is what happens on approval:
POST /v1/ordersissues the bond as soon as it is approved. For an instant-issue form, that means the bond and its documents come back in the same response.POST /v1/quotesstops at approval. You get a premium and an order id, and the bond is not issued until you callPOST /v1/orders/{id}/issue.
Use a quote when the customer has to accept a price before you bind, or when you need to edit the order after pricing it. Use an order when the price is already agreed.
You can also call POST /v1/orders/validate first. It runs the same validation as a real order without creating anything, which is the cheapest way to surface field errors in your own UI.
Order status
Every order carries a status:
| Status | Meaning |
|---|---|
submitted |
The order has been received and is awaiting a decision |
pending |
Waiting on approval, either automated or from an underwriter |
approved |
Approved and ready to issue |
auto_approved |
Approved automatically and ready to instant issue |
applicant_pending |
Waiting on the applicant to supply more information |
fulfilled |
Issued. Bond documents are ready |
declined |
Underwriting declined the bond |
cancelled |
Cancelled. It cannot be issued or edited |
saved |
Saved for later |
failed |
A technical problem prevented fulfillment |
Bond
Once an order is fulfilled it becomes a bond, identified by a bond_number such as IA5199999. Servicing endpoints — cancel, non-renew, reinstate, endorse, renewals — all live under /v1/commercial_bonds/{bond_number}.
Documents
Issuing produces PDFs: the executed bond form, the application, an invoice, and the power of attorney. The order response includes a documents array of filenames and URLs, and you fetch each one from /v1/orders/{order_id}/documents/{document_type}. Endorsements produce their own documents under the update that created them.
Correction vs. update
These sound alike and are not the same thing.
- A correction fixes a mistake. It rewrites the bond as if the data had always been right, and it is only available on certain fields within 60 days of submission. Ask
/v1/orders/correctable_fieldswhich fields qualify. - An update (or endorsement) records a real-world change, such as an address change or a bond amount increase. It creates an update record with its own documents and may generate premium. Ask
/v1/orders/updateable_fieldswhich fields qualify.
Account submission
Commercial bonds are written form by form. Contract bonds instead start with an account — the contractor or developer relationship. An account submission sends that account to the RAP program for an underwriting decision, and returns rap_limits once approved. See the Account Submission Work Flow.
Producer and attorney-in-fact
Orders name a producer_name (the licensed agent selling the bond) and an attorney_in_fact (the person authorized to execute the bond on behalf of the surety). GET /v1/agency/producers returns the producers valid for your agency, so you can populate that field from a list instead of free text.
How a bond gets approved
Approval depends on the obligation and the bond amount, and you can predict it before you submit:
- Instant issue. If the obligation has
instant_issueand your bond amount is at or belowinstant_issue_upper_limit, the bond is approved without a credit check and can be issued in the same call. - Automated underwriting. If the obligation has
automated_underwritingand the amount is at or belowautomated_underwriting_upper_limit, we run a credit decision. The order comes back approved or declined. - Manual underwriting. Anything above those limits — or an obligation flagged
manual_approval— goes to a Merchants underwriter and comes backpending. Orders can also land inpendingwhen a credit check fails or owner information is missing.
Design for pending. Poll GET /v1/orders/{order_id} for the status rather than assuming an order that did not come back approved has failed. See Obligations for the full rules.
Requests and responses
The API speaks JSON over HTTPS. Send Content-Type: application/json on requests with a body, and your key in the API_KEY header on every request. See Authentication.
| Environment | Base URL |
|---|---|
| Staging | https://api.mbctestweb.com |
| Production | https://api.merchantsbonding.com |
Build and test against staging. Bonds issued in production are real bonds with real premium.
| Convention | Rule |
|---|---|
| Versioning | Endpoints are namespaced by version, currently /v1 with a small number of /v2 endpoints. Existing versions stay backward compatible |
| Dates | ISO 8601, YYYY-MM-DD (for example 2024-01-15) |
| Bond amounts | Whole dollars — 5000 means $5,000 |
| Premium and pricing | Cents — 35500 means $355.00 |
| Success | Every response carries a success boolean |
| Failure | success is false and an errors object maps field names to messages. See Errors |
| State codes | Two-character USPS abbreviations |
Where to go next
- Quickstart — issue your first bond in four calls.
- Work Flow — step-by-step call sequences for ordering, quoting, issuing, endorsing, canceling, and reinstating.
- Account Submission Work Flow — submitting contract accounts to RAP.
- Obligations — the approval rules in detail.
- Errors — error format and status codes.
- API Reference — every endpoint, with schemas you can try in the browser.
- Glossary — surety terms and API terms.
Authentication
Merchants Bonding supports two ways to authenticate requests:
- API key: a long-lived key sent in the
API_KEYheader on every request. - OAuth 2.0 client credentials: exchange a client ID and secret for a short-lived bearer token, then send that token in the
Authorizationheader.
Both are tied to the same agency and grant the same capabilities, so every endpoint accepts either one. Choose whichever fits your integration best. OAuth keeps your long-lived secret off of everyday requests.
Credentials are issued and maintained by Merchants Bonding Company. Contact us to get them, and request staging credentials first so you can build against https://api.mbctestweb.com before going live.
Your credentials identify exactly one agency. Every request is scoped to that agency, which is why no endpoint takes an agency identifier. The obligations you can see, the orders you can read, and the bonds you can service are all the ones belonging to your agency.
Your credentials also control which capabilities you have: submitting work in progress updates, commercial bond information, or both.
API Key
curl "https://api.mbctestweb.com/v1/obligations" \
-H 'API_KEY: keykeykey'
When the key is missing or invalid the API responds
401 Unauthorizedwith a plain-text body:
unauthorized
Include your key in the API_KEY header on every request:
API_KEY: keykeykeykey
OAuth 2.0
The API supports the OAuth 2.0 client credentials grant, which is designed for server-to-server integrations. There is no user login or browser redirect. The flow has two steps:
- Request an access token from
POST /oauth/tokenusing your client ID and client secret. - Send the access token as
Authorization: Bearer <access_token>on your API requests until it expires, then request a new one.
Requesting an Access Token
curl "https://api.mbctestweb.com/oauth/token" \
-X POST \
-H 'Content-Type: application/json' \
-d '{
"grant_type": "client_credentials",
"client_id": "mbc_4f3c1d9e8b7a6c5d4e3f2a1b0c9d8e7f",
"client_secret": "secretsecretsecret",
"scope": "orders"
}'
Credentials can also be sent with HTTP Basic auth instead of in the body:
curl "https://api.mbctestweb.com/oauth/token" \
-X POST \
-u 'mbc_4f3c1d9e8b7a6c5d4e3f2a1b0c9d8e7f:secretsecretsecret' \
-d 'grant_type=client_credentials'
A successful request returns:
{
"access_token": "tokentokentoken",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "orders"
}
POST /oauth/token
| Parameter | Required | Description |
|---|---|---|
| grant_type | Yes | Must be client_credentials. |
| client_id | Yes | Your client ID. It starts with mbc_. |
| client_secret | Yes | Your client secret. |
| scope | No | A space delimited list of the scopes you want on the token. Leave it out to receive every scope your credentials allow. |
The body can be sent as JSON or as form data (application/x-www-form-urlencoded). If you send client_id and client_secret with HTTP Basic auth, leave them out of the body.
Responses from this endpoint include Cache-Control: no-store and must not be cached.
Scopes
| Scope | Allows |
|---|---|
wip |
Submitting work in progress updates |
orders |
Validating and submitting orders and servicing commercial bonds |
A token can only carry scopes that your credentials have been granted. Requesting a narrower set of scopes is a good way to limit what a token can do if it is ever exposed.
Using the Access Token
curl "https://api.mbctestweb.com/v1/obligations" \
-H 'Authorization: Bearer tokentokentoken'
When the token is missing, invalid, or expired the API responds
401 Unauthorizedwith a plain-text body and aWWW-Authenticate: Bearer realm="Merchants Bonding API"header:
unauthorized
Send the token in the Authorization header on every request:
Authorization: Bearer tokentokentoken
Access tokens expire one hour after they are issued. Use expires_in (in seconds) to track when that will happen. There are no refresh tokens. When a token expires, request a new one with your client credentials. We recommend caching the token and reusing it until shortly before it expires rather than requesting a new token for every API call.
If a token is used on an endpoint its scopes do not cover, the API responds 405 Method Not Allowed:
{"success": false, "errors": "token does not allow that action"}
When we reissue your client secret, every access token issued with the old secret stops working immediately.
Token Errors
Errors from
POST /oauth/tokenfollow the OAuth 2.0 format:
{
"error": "invalid_client",
"error_description": "Client authentication failed"
}
| Status | Error | Meaning |
|---|---|---|
| 400 | unsupported_grant_type |
grant_type was missing or something other than client_credentials. |
| 400 | invalid_scope |
The requested scope includes something your credentials have not been granted. |
| 401 | invalid_client |
The client ID or client secret is wrong, or your credentials have been revoked. |
| 500 | server_error |
Something went wrong on our side. Try the request again later. |
Quickstart
This walks through issuing a real, instant-issue commercial bond on staging in five calls. Every example uses the staging host, https://api.mbctestweb.com, and the API_KEY header described in Authentication.
Pick an instant-issue form for your first bond — a notary bond is the usual choice — so the bond issues without waiting on underwriting.
1. Find a bond form
curl "https://api.mbctestweb.com/v1/obligations?state=IA" \
-H 'API_KEY: keykeykey'
JSON response:
{
"success": true,
"obligations": [
{
"id": 118354,
"state": "IA",
"name": "PRE-EXECUTED $10,000 Notary Public Bond",
"license_plate": "PNOTR",
"bond_amounts": [10000],
"term_length": 4,
"hub_express_enabled": true
}
]
}
GET /v1/obligations lists every bond form your agency can write. Add ?state= to narrow it to one state.
This is also the fastest way to confirm your key works. A 401 means the key is missing or wrong; an empty list means the key is valid but the agency is not appointed for that state.
Keep the id — that is the obligation_id you will order against.
2. Check what the form requires
curl "https://api.mbctestweb.com/v1/obligations/118354" \
-H 'API_KEY: keykeykey'
JSON response, abbreviated:
{
"success": true,
"information": {
"title": "$10,000 Notary Public Bond",
"state": "IA",
"obligee_name": "State of Iowa",
"bond_amounts": [10000],
"years_increments": [4],
"term_length": 4,
"instant_issue": true,
"instant_issue_upper_limit": 10000,
"requires_wet_signature": false,
"can_renew": true,
"standard_fields": [
{ "name": "bond_amount", "field_type": "numeric" },
{ "name": "principal_name", "field_type": "text" },
{ "name": "effective_date", "field_type": "ISO8601" }
],
"form_specific_fields": [
{
"name": "not_p_name",
"field_type": "text",
"label": "Name of notary acknowledging for the surety",
"tooltip": ""
}
]
},
"price_quotes": {
"10000": { "1 year": 10000, "4 years": 30000 }
}
}
GET /v1/obligations/{obligation_id} returns the contract for that form: the bond amounts and term lengths you may use, the standard_fields every order needs, and the form_specific_fields unique to this form.
Check instant_issue and instant_issue_upper_limit here. If instant_issue is true and your bond amount is at or below the limit, step 4 will issue the bond outright.
price_quotes gives the premium in cents, keyed by bond amount and term, so you can show a price before the customer commits.
3. Validate the order
curl -X POST "https://api.mbctestweb.com/v1/orders/validate" \
-H 'API_KEY: keykeykey' \
-H 'Content-Type: application/json' \
-d '{
"obligation_id": 118354,
"bond_amount": 10000,
"principal_name": "Construction Company, Inc.",
"principal_address1": "515 Oak Drive",
"principal_city": "Urbandale",
"principal_state": "IA",
"principal_zip": "50322",
"effective_date": "2024-01-15",
"expiration_date": "2028-01-15",
"attorney_in_fact": "John Wolf",
"producer_name": "Bill Billings",
"state": "IA",
"form_specific_fields": {
"not_p_name": "Notary Public Name"
}
}'
JSON response, when valid:
{
"success": true,
"valid": true
}
JSON response, when invalid:
{
"success": false,
"valid": false,
"errors": {
"bond_amount": [
"is not a valid bond amount for obligation. Valid amounts are 10000"
]
}
}
POST /v1/orders/validate runs the same checks as a real order without creating anything. Use it to surface field errors in your own UI before the customer pays.
Two details worth knowing up front: bond_amount is in whole dollars, and dates are ISO 8601 YYYY-MM-DD.
4. Place the order
curl -X POST "https://api.mbctestweb.com/v1/orders" \
-H 'API_KEY: keykeykey' \
-H 'Content-Type: application/json' \
-d '{
"obligation_id": 118354,
"bond_amount": 10000,
"principal_name": "Construction Company, Inc.",
"principal_address1": "515 Oak Drive",
"principal_city": "Urbandale",
"principal_state": "IA",
"principal_zip": "50322",
"effective_date": "2024-01-15",
"expiration_date": "2028-01-15",
"attorney_in_fact": "John Wolf",
"producer_name": "Bill Billings",
"state": "IA",
"form_specific_fields": {
"not_p_name": "Notary Public Name"
}
}'
JSON response, abbreviated:
{
"success": true,
"order": {
"id": 99999,
"bond_number": "IA5199999",
"status": "fulfilled",
"bond_amount": 10000,
"premium": 30000,
"effective_date": "2024-01-15",
"expiration_date": "2028-01-15",
"documents": [
{
"filename": "bond_form.pdf",
"url": "https://api.mbctestweb.com/v1/orders/99999/documents/bond_form"
},
{
"filename": "invoice.pdf",
"url": "https://api.mbctestweb.com/v1/orders/99999/documents/invoice"
}
]
}
}
Send the same payload to POST /v1/orders. Because the form is instant issue, the bond is issued in this one call: the response comes back fulfilled with a bond_number and a documents array.
premium is in cents.
The bond is now visible in the Merchants Bonding Hub, exactly as if it had been written there.
5. Get the documents
curl "https://api.mbctestweb.com/v1/orders/99999/documents/bond_form" \
-H 'API_KEY: keykeykey' \
-o bond_form.pdf
The response body is the PDF itself:
%PDF-1.1
...
%%EOF
Each entry in the documents array is a direct link. GET /v1/orders/{order_id}/documents/{document_type} returns the PDF bytes, so write the response to a file rather than parsing it as JSON.
| Document type | Contents |
|---|---|
bond_form |
The completed, executed bond form |
bond_application |
The bond application |
invoice |
The invoice |
power_of_attorney |
The power of attorney |
endorsement |
Present once the bond has been endorsed |
bundle |
The bond form, power of attorney, and any endorsements in one PDF |
Next steps
- Quote before you bind, and issue later — see Quote commercial bond.
- Service the bond you just wrote — Endorse or update, Cancel, Reinstate.
- Submit a contract account to RAP — Account Submission Work Flow.
- Browse every endpoint and try it in the browser — API Reference.
Work Flow
There are a number of ways to order, quote and issue commercial bonds. For instant issue bonds, which do not require credit check, you can order and issue the bond in a single step. See the Order commercial bonds workflow below.
If you prefer to get a quote before issuing a bond, you can follow the "Quote commercial bond" flow below.
Below lists a number of different work flows and operations. To see the details of the API calls, see the API Reference
Order commercial bonds
This work flow allows you to order and issue a bond in a single API call. After doing that you can retrieve the documents.
- Use
GETon/v1/obligationsfor obligation id's you will use to validate or submit and order. - Use
POSTon/v1/orders/validateto send order parameters and determine if it would succeed. optional - Use
POSTon/v1/ordersto send us an order and issue it in a single step. - Use
GETon/v1/orders/<order id>to look up an order. - Use
GETon/v1/orders/<order id>/documentsto retrieve documents for an order. - Use
GETon/v1/orders/<order id>/documents/<identifier>to retrieve a specific document for an order.
Quote commercial bond
This creates a quote for a bond that is valid for 60 days. When the quote is approved you can then issue the bond with another API call. You can also edit quotes to change information.
- Use
GETon/v1/obligationsfor obligation id's you will use to validate or submit and order. - Use
GETon/v1/obligations/<obligation id>to find out what optional fields are available on the obligation. - Use
POSTon/v1/quotesto send request for a quote on a specific obligation for an applicant. This will return an order id.
Edit quote
You can edit approved quotes and orders. You cannot edit an issued or fulfilled order. _Note: This is a v2 endpoint
- Use
PATCHon/v2/orders/<order id>to send request with a JSON payload of attributes you want to change.
Issue commercial bond
This lets you issue a bond from a quote. You can only issue approved bonds.
- Use
POSTon/v1/orders/<order id>/issueto bind the quote and issue the bond. This only works if the order status is 'approved'. - Use
GETon/v1/orders/<order id>/documentsto retrieve documents for an order. - Use
GETon/v1/orders/<order id>/documents/<identifier>to retrieve a specific document for an order.
Cancel commercial bond
- Use
POSTon/v1/commercial_bonds/<bond number>/cancelto cancel the bond.
Cancellations current support two different reason codes:
499 - This is a cancellation because of a principal request
500 - This is a cancellation because of non-payment
If you submit a reason code of 499 and use an effective date of the cancellation that matches the bond's effective date, we will cancel the bond flat.
Non-renew a commercial bond
- Use
POSTon/v1/commercial_bonds/<bond number>/nonrenewto cancel a bond as a non-renew.
Reinstate commercial bond
- Use
POSTon/v1/commercial_bonds/<bond number>/reinstateto reinstate the bond. It will be reinstated as of the date of cancellation.
Endorse or update commercial bond
- Use
PATCHon/v1/commercial_bonds/<bond number>to update the bond with changes. The changes are passed in as JSON with attributes of the changed fields.
The PATCH will respond with an update object with information about what changed. Use the id with the GET /v1/commercial_bonds/<bond number>/updates/<updated id> to retrieve additional information including documents. Those documents may include an endorsement, power of attorney, or invoice depending on the change.
Account Submission Work Flow
Account submissions let you create a new contract-bond account through the RAP program without manual data entry. There are two program types: RAP for contractors, and RAP for Developers for real-estate developers (everything in RAP plus project details). Both are submitted to the same endpoint and are told apart by the program_type field.
Your submission is automatically scoped to the agency tied to your API key, so you never send an agency id. To see the details of the API calls, see the API Reference.
Possible statuses
A submission moves through the following statuses. The create call returns pending; the others appear as underwriting reviews the account.
- pending: The submission has been received and is awaiting an underwriting decision. This is the initial status returned by the create call.
- approved: Underwriting approved the account. Bonds can be written up to the amounts in
rap_limits. - referred: The submission could not be decided automatically and is being reviewed by an underwriter.
- declined: Underwriting declined the account.
- applicant_pending: Merchants is waiting on the applicant before the account can proceed, for example to complete the indemnity agreement e-signature.
- archived: The submission has been archived and is no longer active.
Submit an account (RAP)
curl -X "POST" "https://api.mbctestweb.com/v1/account_submissions" \
-H 'API_KEY: keykeykey' \
-H 'Content-Type: application/json' \
-d $'{
"program_type": "RAP",
"company_name": "Construction Company, Inc.",
"dba": "ConCo",
"type_of_work": "General Construction",
"legal_structure": "LLC",
"producer_name": "Bill Billings",
"address": {
"line1": "123 Main St.",
"city": "Urbandale",
"state": "IA",
"zip": "50322"
},
"indemnity_details": {
"name": "Carl Miller",
"title": "Owner",
"email": "owner@company.com"
},
"owners": [
{
"name": "Carl Miller",
"ownership_percentage": 100,
"marital_status": "Married",
"ssn": "123-45-6789",
"address": {
"line1": "123 Main St.",
"city": "Urbandale",
"state": "IA",
"zip": "50322"
},
"spouse": {
"name": "Rebecca Miller",
"email": "spouse@company.com"
}
}
],
"program_questions": {
"is_new_business": false,
"is_business_in_new_york_borough": false,
"has_ever_declared_bankruptcy": false,
"has_ever_defaulted_on_contract": false,
"has_previous_surety_claim": false,
"has_recent_lawsuit": false,
"has_bonds_with_another_surety": false
}
}'
The above command returns JSON structured like this:
{
"success": true,
"account_submission": {
"id": "12345",
"status": "pending",
"program_type": "RAP",
"company_name": "Construction Company, Inc.",
"producer_name": "Bill Billings",
"rap_limits": {
"single_bond_limit": 1000000,
"aggregate_limit": 1000000
},
"created_at": "2024-10-02 14:49:23.573743000 -0500",
"updated_at": "2024-10-02 14:49:23.573743000 -0500"
}
}
This work flow creates a contract account for a contractor.
- Use
GETon/v1/agency/producersto look up the valid producers for your agency. Theproducer_nameyou submit must match one of these (case-insensitive), or the submission is rejected. - Gather the account details: company, address, type of work, legal structure, the indemnity signer, the program questions, and the owners. The owners'
ownership_percentagevalues must total between 90 and 100. - Use
POSTon/v1/account_submissionswithprogram_typeset toRAP. On success you receive201with the created submission, itsstatusofpending, and therap_limitsthat apply to the account. - If the request is invalid you receive
422with a body of{ "success": false, "errors": { ... } }. Correct the reported fields and resubmit. - Keep the
idfrom the response so you can check the status of the submission.
A few things to keep in mind:
- Providing an
emailinindemnity_detailsmay trigger an e-signature email to that person for the indemnity agreement. Omit the email if you do not want that sent yet. program_questions.additional_detailsis required whenhas_previous_surety_claim,has_recent_lawsuit, orhas_bonds_with_another_suretyistrue.ssnis write-only. It is accepted on submission but never returned in any response.
Submit an account (RAP for Developers)
This work flow creates a contract account for a real-estate developer. It is the RAP submission plus a project and three additional program questions.
- Follow the steps above, but set
program_typetoRAP for Developers. - Include a
project_detailsobject. Set itsbond_typeto eitherPerformanceorMaintenance; each requires a different set of fields (see the API Reference). - Answer the three additional program questions:
has_forfeiture_or_pay_on_demand_language,has_strict_financial_guarantees_or_obligations, andhas_environmental_or_remediation_bonds. - Use
POSTon/v1/account_submissionsand handle the response as you would for aRAPsubmission.
Request increased bond capacity
The base program limit is returned in rap_limits. To request a higher limit, include a capacity_request describing the applicant's largest completed project in the past three years.
- Set
capacity_request.requesting_increased_capacitytotrue. - Provide the
largest_project_owner,largest_project_amount, andlargest_project_description. These are required whenever increased capacity is requested. - Submit the account as usual. The
rap_limitsin the response reflect the capacity your submission qualifies for.
Check the status of a submission
- Use
GETon/v1/account_submissions/<account_submission_id>to retrieve the currentstatusalong with the full submission (without any SSNs). - Poll this endpoint to follow the submission from
pendingto a finalapproved,referred, ordeclined. Areferredsubmission is being reviewed by an underwriter and will resolve toapprovedordeclined.
Obligations
There a some specific rules around bond approvals that are determined by the values below.
- instant_issue: when true the bond will be approved instantly if the bond amount is below the instant_issue_upper_limit value
- instant_issue_upper_limit: the top bond dollar amount where instant issue could happen
- automated_underwriting: when true we will try to credit approve the bond when the bond amount is below the automated_underwriting_upper_limit value
- automated_underwriting_upper_limit: the top bond dollar amount where credit approval could happen
Anything quote or order with a bond amount above the automated_underwriting_upper_limit will end up as pending and need manual approval from an underwriter inside Merchants. There are other types of quotes that could be pending. For example if the credit check fails. Or when we don't recieve owner information for the quote.
Underwriting questions
Some obligations, starting with probate bonds, list underwriting questions in their form_specific_fields with a field_type of select. The label holds the question text.
Answer a question by sending "Yes" or "No" in the order's form_specific_fields, keyed by the question's name:
"form_specific_fields": {
"removed_as_fiduciary": "No"
}
Any value other than "Yes" or "No" is rejected with a 400 naming the valid options.
Errors
{
"success": false,
"errors": {
"field": [
"a reason",
"another reason"
],
"another_field": [
"a reason",
]
}
}
There will be an errors key in the response, which will typically have a field
or attribute name (bond_amount), with possibly multiple error messages.
| Error Code | Meaning |
|---|---|
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 405 | Method Not Allowed |
| 406 | Not Acceptable |
| 500 | Internal Server Error |
Glossary
Surety bond terms
| Term | Description |
|---|---|
| Account | A principal (business or individual) that has an established relationship with an agency for bonding purposes. |
| Agency | An insurance agency authorized to sell and service surety bonds on behalf of Merchants Bonding Company. |
| Attorney-in-Fact | A licensed agent authorized to sign bonds on behalf of the surety company. |
| Bond Amount | The maximum liability/coverage of the bond, also known as the penal sum. |
| Cancellation | The termination of a bond before its expiration date, initiated by the principal, obligee, or surety. May result in a return premium calculated on a flat (full refund) or pro-rata (partial refund) basis. Notices of Cancellation are sent to the principal and obligee. |
| Commercial Bond | A surety bond that guarantees compliance with licenses, permits, or regulations (e.g., notary bonds, contractor license bonds). Also known as a license and permit bond. |
| Contract Bond | A surety bond that guarantees performance of a construction contract, including payment and performance bonds, bid bonds, and maintenance bonds. |
| License Plate | Internal code identifying an obligation type (e.g., "PNOTR" for Notary). Used in order requests. |
| Non-Renewal | A decision by the surety not to renew a bond beyond its current term. Takes effect at the bond's expiration date and typically results in no return premium, since the bond completes its full term. |
| Obligee | The party (typically a government entity) that requires the bond and is protected by it. |
| Obligation | A specific bond type for a particular state and bond amount combination. Each obligation has a unique ID and may have state-specific requirements. |
| Premium | The amount paid for the bond. |
| Principal | The party who purchases the bond and is obligated to perform the bonded obligation (e.g., a contractor or notary). |
| Producer | The licensed agent at the agency who sells the bond. GET /v1/agency/producers returns the producers valid for your agency. |
| RAP | The Merchants program for writing contract bonds for small and emerging contractors. New accounts enter it through an account submission. |
| Reinstatement | The restoration of a previously cancelled or terminated bond back to active status. Reverses a prior cancellation, restores premium and commission amounts, and generates rescind notices to the principal and obligee. |
| Surety | The insurance company (Merchants Bonding Company) that guarantees the principal's performance. |
API terms
| Term | Meaning |
|---|---|
| API key | The credential that identifies your agency on every request. Sent in the API_KEY header. See Authentication. |
| Order | A request to issue a bond immediately upon approval. Contains principal information, bond details, and payment information. |
| Quote | A request to obtain bond approval without immediate issuance. Valid for 60 days and requires a separate issue call to bind the bond. |
| Correction | A change to an existing bond or order that fixes a mistake, available only within 60 days of the submission date and only on certain fields. |
| Update | A change that records a real-world event, such as an endorsement. Creates an update record with its own documents and may generate premium. |
| Correctable field | A field the corrections API can change. List them with GET /v1/orders/correctable_fields. |
| Updateable field | A field the updates API can change. List them with GET /v1/orders/updateable_fields. |
| Instant issue | An obligation that can be approved and issued with no credit check, up to instant_issue_upper_limit. |
| Automated underwriting | An obligation that can be approved by credit decision, up to automated_underwriting_upper_limit. |
| Hub Express | A shareable link that lets a principal start a bond application themselves. Available for obligations with hub_express_enabled; list an obligation's links with GET /v1/obligations/{obligation_id}/hub_express_links. |