We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
GraphQL
The Corvus Insurance API is a GraphQL API with a single endpoint. How requests and responses are shaped, the terms the reference pages use, and how to use the API well.
What GraphQL is
The Corvus Insurance API is a GraphQL API. You send every operation to one endpoint, /q, as an HTTP
POST
with a JSON body. There is no REST endpoint per resource.
GraphQL is a query language for APIs. Each request carries a document that names one operation and lists the fields you want back. The response contains those fields and no others.
| Topic | REST | This API (GraphQL) |
|---|---|---|
| Endpoints | One URL per resource. | One endpoint, /q, for every operation. |
| HTTP method | GET, POST, PUT, PATCH or DELETE, by action. | POST for every request. A query reads data; a mutation changes it. |
| Response fields | Fixed by the server. | Exactly the fields you select. |
| Errors | Reported by the HTTP status code. | Reported in an errors array, usually with HTTP 200. |
Vocabulary
The terms used on the reference pages.
- Query
- An operation that reads data and changes nothing. For example,
quoteRequestslists quote requests. - Mutation
- An operation that creates or changes data. For example,
createClientcreates a client. - Operation name
- The name you give an operation after the
queryormutationkeyword, such asListQuoteRequestsinquery ListQuoteRequests. Send the same name asoperationName. - Variables
- Typed inputs that the operation declares with
$, such as$first: Int!, and that you send separately in thevariablesobject. The Arguments table on each reference page lists them. - Selection set
- The fields inside
{ }that you want back. The response contains these fields and no others. The Response fields table on each reference page lists the fields you can select. - Fragment
- A named selection set that you can reuse. Declare it with
fragment Name on Type { ... }and include it with...Name. - Input type
- An object type used only as an argument, such as
AddressInput. Send it as a JSON object invariables. - Enum
- A type with a fixed set of values, such as
ProductType(CYBERorTECH_EO). Send an enum value invariablesas a JSON string, spelt exactly as listed. - Non-null (!)
- A type that ends in
!, such asID!, is never null. On an argument it means the value is required. On a response field it means the field always has a value.
Request shape
- Method:
POST, for queries and mutations alike. -
Endpoint:
https://api-sandbox.corvusinsurance.com/qin the sandbox andhttps://crowbar.corvusinsurance.com/qin production. - Headers: the authentication headers and JSON content headers listed on Authentication.
- Body: a JSON object with the keys in the Request body keys table. Send one operation per request.
| Key | Type | Required | Description |
|---|---|---|---|
query |
string | Required | The GraphQL document: the operation text, as a JSON string. |
variables |
object | Optional | Values for the variables the operation declares. Required when it declares a non-null (!) variable. |
operationName |
string | Optional | The name of the operation to run. Required when query contains more than one operation. |
POST /q HTTP/1.1Host: api-sandbox.corvusinsurance.comX-API-KEY: <your API key>X-USER-EMAIL: <email of the user making the request>X-USER-NAME: <name of the user making the request>Content-Type: application/jsonAccept: application/json{"query": "query GetQuoteRequest($id: ID!) { quoteRequest(id: $id) { id status } }", "variables": {"id": "9wrvdpN5QaWlJ5PomsPe1g"}, "operationName": "GetQuoteRequest"}
Response shape
The response body is a JSON object with up to two keys:
| Key | Description |
|---|---|
data |
The fields you selected, in the shape of your selection set. null, or left out, when the operation could not run. |
errors |
A list of errors, each with a message and usually locations and path. Left out when there are no errors. |
errors
on every response. Requests rejected before GraphQL runs, such as a missing API key or a body with no query, return 400, 401 or 404 (see Errors).
Partial success
One request can succeed for some fields and fail for others. The failed field is null, and an entry in
errors
names it in path. The other fields keep their data.
If the failed field is non-null (!), the null moves up to the nearest field that can be null. For a non-null top-level field, such as quoteRequest, the whole of
data
is null.
query Dashboard { policies(first: 1) { edges { node { id } } } quoteRequests { edges { node { id } } }}
{ "data": { "policies": { "edges": [{ "node": { "id": "oP8eyTn2QjeMbWj0rH6xTw" } }] }, "quoteRequests": null }, "errors": [ { "message": "You must either supply `:first` or `:last`", "path": ["quoteRequests"], "locations": [{ "line": 5, "column": 3 }] } ]}
Invalid documents
If the document cannot be parsed or validated, for example a misspelt field or a missing required variable, nothing runs. The response has
errors
and no
data
key, still with HTTP 200.
{ "errors": [ { "message": "Cannot query field \"nope\" on type \"QuoteRequestConnection\".", "locations": [{ "line": 1, "column": 35 }] } ]}
Worked example: list quote requests
One complete request and its response.
This query lists the first 25 quote requests with status
QUOTES_SHARED
for clients whose broker team includes the user in X-USER-EMAIL.
1. Write the operation
query ListQuoteRequests($first: Int!, $after: String, $statusIn: [QuoteRequestStatus!]) { quoteRequests(first: $first, after: $after, statusIn: $statusIn) { pageInfo { hasNextPage endCursor } edges { node { id status productType client { id name } } } }}
2. Put it in the request body
Save the body as request.json. The operation is the
query
string; its inputs go in variables.
{ "query": "query ListQuoteRequests($first: Int!, $after: String, $statusIn: [QuoteRequestStatus!]) { quoteRequests(first: $first, after: $after, statusIn: $statusIn) { pageInfo { hasNextPage endCursor } edges { node { id status productType client { id name } } } } }", "variables": { "first": 25, "statusIn": ["QUOTES_SHARED"] }, "operationName": "ListQuoteRequests"}
3. Send the request
curl https://api-sandbox.corvusinsurance.com/q \ -X POST \ -H "X-API-KEY: $CORVUS_API_KEY" \ -H "X-USER-EMAIL: broker@example.com" \ -H "X-USER-NAME: Example Broker" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ --data @request.json
4. Read the response
The keys come back in alphabetical order, not in the order of the selection set. Read each field by name. To get the next page, send the request again with
after
set to pageInfo.endCursor.
{ "data": { "quoteRequests": { "edges": [ { "node": { "client": { "id": "r_ueqcfTSheKXZJ8zwbk_g", "name": "Test Client" }, "id": "9wrvdpN5QaWlJ5PomsPe1g", "productType": "CYBER", "status": "QUOTES_SHARED" } } ], "pageInfo": { "endCursor": "YXJyYXljb25uZWN0aW9uOjA=", "hasNextPage": false } } }}
Best practices
Request only the fields you need
Select only the fields your integration uses, and only fields shown in these docs. Some fields are not available to API partners; selecting one returns
unauthorized
and can null the object that contains it (see Fields not available to API partners).
Pass values as variables
Declare each input on the operation and send its value in variables. Never insert values into the
query
string. Variables are typed and checked by the API and need no escaping.
query GetQuoteRequest($id: ID!) { quoteRequest(id: $id) { id status }}
Name every operation
Give every operation a name, such as query ListQuoteRequests, and send it as operationName. A document with more than one operation and no
operationName
is rejected. Include the name when you contact support about a request.
Check errors on every response
Treat a response as successful only when
errors
is missing or empty. HTTP 200 alone does not mean the operation succeeded. See Errors
for the common messages and how to read validation errors.
Handle partial results
When a response has both
data
and errors, use the fields that have values and handle each error by its path. Do not read a
null
field as "no value" without checking whether an error names it (see Partial success).
Use fragments for repeated selections
When several operations select the same fields of a type, define them once as a fragment and include it with ...Name.
query ClientQuoteRequests($first: Int!, $clientId: ID!) { quoteRequests(first: $first, clientId: $clientId) { edges { node { ...QuoteRequestSummary } } }}fragment QuoteRequestSummary on QuoteRequest { id status productType}
Paginate with cursors
-
List operations return a connection. Pass
firston every request; leaving it out returns an error. -
Each list operation has a maximum page size. A larger
firstis reduced to the maximum without an error. -
To get the next page, pass
pageInfo.endCursorfrom the last response asafter. -
Stop when
hasNextPageisfalseor a page has noedges.hasNextPagecan betruewhen the next page is empty. - Treat cursors as opaque. Do not decode, build or store them.
query ListQuoteRequests($first: Int!, $after: String) { quoteRequests(first: $first, after: $after) { pageInfo { hasNextPage endCursor } edges { node { id } } }}
Retry only requests that can succeed on retry
-
Do not retry a request that failed with a validation error,
unauthorized,not_found, or a 400, 401 or 404 status. Fix the request first. - Retry network failures, timeouts and 5xx statuses with exponential backoff and a limit on attempts.
- Set a timeout on every request. Treat a timeout as an unknown outcome, not a failure.
-
You can retry a query safely. Before you retry a mutation whose outcome is unknown, query for the record first: repeating
createClientorcreateQuoteRequestcreates a duplicate, and duplicate clients or submissions may delay quote delivery.
Use these docs as the schema reference
The operations and fields documented here are the ones supported for API partners. The schema contains more types and fields than API partners can use, and an undocumented field may return
unauthorized
or change without notice. Do not discover operations or fields from the schema itself. If you need data that is not documented, contact api@corvusinsurance.com.
Read fields by name and allow for null
Do not depend on the order of keys in a response; read each field by name. A field whose type has no
!
can be null. Handle
null
for every such field you select.
Learn more about GraphQL
The official GraphQL documentation covers the language in depth: