Appearance
Integration Walkthrough
Follow a complete FirstCyber quote from authentication through policy issuance. Each step shows a copy-pasteable request and response. For endpoint field reference, see the FirstCyber Quote Service.
Sandbox first
Run this walkthrough against https://api-sandbox.k2cyber.co with sandbox Partner Portal credentials. For Direct Bill bind testing, use direct@k2cyber.ai as the broker email. See Quick Start for environment setup.
1. Authenticate
Obtain a bearer token with your M2M client credentials. Cache the token and refresh before expires_in elapses.
bash
curl -X POST https://api-sandbox.k2cyber.co/auth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=<CLIENT_ID>&client_secret=<CLIENT_SECRET>&grant_type=client_credentials&scope=quote"javascript
const body = new URLSearchParams({
client_id: process.env.K2_CLIENT_ID,
client_secret: process.env.K2_CLIENT_SECRET,
grant_type: "client_credentials",
scope: "quote",
});
const response = await fetch("https://api-sandbox.k2cyber.co/auth/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body,
});
const { access_token, expires_in } = await response.json();python
import os
import requests
response = requests.post(
"https://api-sandbox.k2cyber.co/auth/token",
data={
"client_id": os.environ["K2_CLIENT_ID"],
"client_secret": os.environ["K2_CLIENT_SECRET"],
"grant_type": "client_credentials",
"scope": "quote",
},
)
token = response.json()Every subsequent request needs both:
Authorization: Bearer <access_token>x-integration-key: <INTEGRATION-KEY>
Credentials come from the Partner Portal.
2. Submit a quote
Send underwriting information to create a quote. The response includes a quote_id and an initial quote_status.
bash
curl -X POST https://api-sandbox.k2cyber.co/quote/firstcyber/submit \
-H "x-integration-key: <INTEGRATION-KEY>" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"broker_email": "broker@example.com",
"insured_name": "Acme Widgets LLC",
"insured_location": {
"address_line1": "510 Meadowmont Village Circle #142",
"address_city": "Chapel Hill",
"address_state": "NC",
"address_zip": "27514"
},
"claims": { "claims_count": 0, "claims_amount": 0 },
"effective_date": "2025-11-01",
"revenue": 5000000,
"naics": 722515,
"question_highrisk": false,
"agg_limit": 1000000,
"retention": 2500
}'javascript
const response = await fetch("https://api-sandbox.k2cyber.co/quote/firstcyber/submit", {
method: "POST",
headers: {
"x-integration-key": process.env.K2_INTEGRATION_KEY,
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
broker_email: "broker@example.com",
insured_name: "Acme Widgets LLC",
insured_location: {
address_line1: "510 Meadowmont Village Circle #142",
address_city: "Chapel Hill",
address_state: "NC",
address_zip: "27514",
},
claims: { claims_count: 0, claims_amount: 0 },
effective_date: "2025-11-01",
revenue: 5000000,
naics: 722515,
question_highrisk: false,
agg_limit: 1000000,
retention: 2500,
}),
});
const result = await response.json();python
import os
import requests
response = requests.post(
"https://api-sandbox.k2cyber.co/quote/firstcyber/submit",
headers={
"x-integration-key": os.environ["K2_INTEGRATION_KEY"],
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
},
json={
"broker_email": "broker@example.com",
"insured_name": "Acme Widgets LLC",
"insured_location": {
"address_line1": "510 Meadowmont Village Circle #142",
"address_city": "Chapel Hill",
"address_state": "NC",
"address_zip": "27514",
},
"claims": {"claims_count": 0, "claims_amount": 0},
"effective_date": "2025-11-01",
"revenue": 5000000,
"naics": 722515,
"question_highrisk": False,
"agg_limit": 1000000,
"retention": 2500,
},
)
result = response.json()Save data.quote_id — every later step uses it. Rating may still be in progress when submit returns with quote_status: "pending"; poll or wait for webhooks until the quote is ready.
3. Wait for rating (poll or webhook)
Choose one approach based on your architecture.
Option A — Poll status
Call GET /status/{id} every 5–10 seconds until quote_status is ready_to_bind (or another terminal / decision state).
bash
curl -X GET "https://api-sandbox.k2cyber.co/quote/firstcyber/status/123e4567-e89b-12d3-a456-426614174000" \
-H "x-integration-key: <INTEGRATION-KEY>" \
-H "Authorization: Bearer <TOKEN>"javascript
const response = await fetch(
"https://api-sandbox.k2cyber.co/quote/firstcyber/status/123e4567-e89b-12d3-a456-426614174000",
{
method: "GET",
headers: {
"x-integration-key": process.env.K2_INTEGRATION_KEY,
Authorization: `Bearer ${access_token}`,
},
},
);
const status = await response.json();python
import os
import requests
response = requests.get(
"https://api-sandbox.k2cyber.co/quote/firstcyber/status/123e4567-e89b-12d3-a456-426614174000",
headers={
"x-integration-key": os.environ["K2_INTEGRATION_KEY"],
"Authorization": f"Bearer {access_token}",
},
)
status = response.json()Stop polling once status is ready_to_bind, approved_rate, underwriter_review, declined, or failed. See Quote Status Values and the Quote Status Flow.
Option B — Subscribe to webhooks
Subscribe early in the Webhook Portal so you receive lifecycle events without polling:
| Event | Meaning |
|---|---|
quote.created | Quote finished rating; status is available |
quote.proposalReady | Quote proposal PDF is ready to download |
policy.created | Policy issued after bind |
4. Download the quote proposal (optional)
Once rating completes and the proposal is available (quote.proposalReady, or status ready_to_bind / approved_rate / underwriter_review), download the PDF.
bash
curl -X GET "https://api-sandbox.k2cyber.co/quote/firstcyber/document/quote-proposal/stream/123e4567-e89b-12d3-a456-426614174000" \
-H "x-integration-key: <INTEGRATION-KEY>" \
-H "Authorization: Bearer <TOKEN>" \
-o quote-proposal.pdfjavascript
const response = await fetch(
"https://api-sandbox.k2cyber.co/quote/firstcyber/document/quote-proposal/stream/123e4567-e89b-12d3-a456-426614174000",
{
method: "GET",
headers: {
"x-integration-key": process.env.K2_INTEGRATION_KEY,
Authorization: `Bearer ${access_token}`,
},
},
);
const buffer = Buffer.from(await response.arrayBuffer());
require("fs").writeFileSync("quote-proposal.pdf", buffer);python
import os
import requests
response = requests.get(
"https://api-sandbox.k2cyber.co/quote/firstcyber/document/quote-proposal/stream/123e4567-e89b-12d3-a456-426614174000",
headers={
"x-integration-key": os.environ["K2_INTEGRATION_KEY"],
"Authorization": f"Bearer {access_token}",
},
)
with open("quote-proposal.pdf", "wb") as f:
f.write(response.content)A 409 means the PDF is not ready yet — wait for the webhook or poll status, then retry. Full availability rules are in GET /document/quote-proposal/stream/{id}.
5. Bind the quote
When status is ready_to_bind, you may initiate a bind. The API returns 202 Accepted immediately; issuance continues asynchronously.
bash
curl -X PUT "https://api-sandbox.k2cyber.co/quote/firstcyber/bind/123e4567-e89b-12d3-a456-426614174000" \
-H "x-integration-key: <INTEGRATION-KEY>" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{}'javascript
const response = await fetch(
"https://api-sandbox.k2cyber.co/quote/firstcyber/bind/123e4567-e89b-12d3-a456-426614174000",
{
method: "PUT",
headers: {
"x-integration-key": process.env.K2_INTEGRATION_KEY,
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({}),
},
);
const result = await response.json();python
import os
import requests
response = requests.put(
"https://api-sandbox.k2cyber.co/quote/firstcyber/bind/123e4567-e89b-12d3-a456-426614174000",
headers={
"x-integration-key": os.environ["K2_INTEGRATION_KEY"],
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
},
json={},
)
result = response.json()6. Get the policy document
After policy.created fires — or GET /status/{id} returns issued — download the policy PDF.
bash
curl -X GET "https://api-sandbox.k2cyber.co/quote/firstcyber/document/policy/stream/123e4567-e89b-12d3-a456-426614174000" \
-H "x-integration-key: <INTEGRATION-KEY>" \
-H "Authorization: Bearer <TOKEN>" \
-o policy.pdfjavascript
const response = await fetch(
"https://api-sandbox.k2cyber.co/quote/firstcyber/document/policy/stream/123e4567-e89b-12d3-a456-426614174000",
{
method: "GET",
headers: {
"x-integration-key": process.env.K2_INTEGRATION_KEY,
Authorization: `Bearer ${access_token}`,
},
},
);
const buffer = Buffer.from(await response.arrayBuffer());
require("fs").writeFileSync("policy.pdf", buffer);python
import os
import requests
response = requests.get(
"https://api-sandbox.k2cyber.co/quote/firstcyber/document/policy/stream/123e4567-e89b-12d3-a456-426614174000",
headers={
"x-integration-key": os.environ["K2_INTEGRATION_KEY"],
"Authorization": f"Bearer {access_token}",
},
)
with open("policy.pdf", "wb") as f:
f.write(response.content)Next steps
- Full endpoint reference: FirstCyber Quote Service
- Status transitions and document matrix: Quote Status Flow
- Webhook delivery and signatures: Webhook Portal
- Specs and Postman: Downloads