Finalize a quotation order
Overview
Quotations follow a lifecycle that turns a seller-created proposal into an order. The buyer can accept or reject a quotation, and once accepted and confirmed, either the buyer or the seller can finalize it to place the order.
Quotation statuses
| Status | Description |
|---|---|
DRAFT | Quotation is being prepared by the seller and is not yet visible to the buyer |
PENDING | Quotation has been sent to the buyer and is awaiting a response |
ACCEPTED | Buyer has accepted the quotation; awaiting seller confirmation if required |
CONFIRMED | Seller has confirmed the accepted quotation; ready to be finalized |
FINALIZED | Quotation has been finalized and an order has been placed |
REJECTED | Buyer has rejected the quotation |
EXPIRED | Quotation validity period (validTo) has passed without action |
CANCELED | Quotation has been canceled by the seller |
settings.requireConfirmation is true, the quotation must reach CONFIRMED status before it can be finalized. The isBlockedFromCheckout flag on the cart will be true until the seller confirms. When requireConfirmation is false, the quotation moves directly from ACCEPTED to being ready for finalization.Prerequisites
- Merchant API key
- JWT token for the authenticated buyer
- Known quotation ID (from
listQuotationCartsorgetQuotationCart)
Goal
- Accept or reject a quotation
- Finalize a confirmed quotation into an order
- Understand quotation statuses and the seller confirmation flow
Architecture at a glance
- Buyer accepts quotation → Seller confirms (if required) → Buyer or seller finalizes → Order created
- Buyer rejects quotation → Quotation closed
APIs used
- Merchant API:
https://merchantapi.geins.io/graphql
Step-by-step
Check the quotation status
Before acting on a quotation, retrieve it to inspect the current status and settings.
Request example
query getQuotationCart(
$quotationId: Guid!
$channelId: String
$languageId: String
$marketId: String
) {
getQuotationCart(
quotationId: $quotationId
channelId: $channelId
languageId: $languageId
marketId: $marketId
) {
id
isBlockedFromCheckout
quotation {
quotationNumber
status
validTo
settings {
requireConfirmation
}
orderId
}
}
}
{
"Accept": "application/json",
"Authorization": "Bearer {JWT_TOKEN}",
"X-ApiKey": "{MERCHANT_API_KEY}"
}
{
"quotationId": "{QUOTATION_ID}",
"channelId": "{CHANNEL_ID}",
"languageId": "{LANGUAGE_ID}",
"marketId": "{MARKET_ID}"
}
curl -X POST https://merchantapi.geins.io/graphql \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {JWT_TOKEN}" \
-H "X-ApiKey: {MERCHANT_API_KEY}" \
-d '{"query":"query getQuotationCart($quotationId: Guid!, $channelId: String, $languageId: String, $marketId: String) { getQuotationCart(quotationId: $quotationId, channelId: $channelId, languageId: $languageId, marketId: $marketId) { id isBlockedFromCheckout quotation { quotationNumber status validTo settings { requireConfirmation } orderId } } }","variables":{"quotationId":"{QUOTATION_ID}","channelId":"{CHANNEL_ID}","languageId":"{LANGUAGE_ID}","marketId":"{MARKET_ID}"}}'
Response example
200 OK{
"data": {
"getQuotationCart": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"isBlockedFromCheckout": true,
"quotation": {
"quotationNumber": "2603-01-0001-00",
"status": "PENDING",
"validTo": "2026-04-30T23:59:59Z",
"settings": {
"requireConfirmation": true
},
"orderId": null
}
}
}
}
Accept a quotation
Call acceptQuotation to indicate the buyer agrees with the quotation terms. The status changes from PENDING to ACCEPTED.
Request example
mutation acceptQuotation(
$quotationId: Guid!
$channelId: String
$languageId: String
$marketId: String
) {
acceptQuotation(
quotationId: $quotationId
channelId: $channelId
languageId: $languageId
marketId: $marketId
)
}
{
"Accept": "application/json",
"Authorization": "Bearer {JWT_TOKEN}",
"X-ApiKey": "{MERCHANT_API_KEY}"
}
{
"quotationId": "{QUOTATION_ID}",
"channelId": "{CHANNEL_ID}",
"languageId": "{LANGUAGE_ID}",
"marketId": "{MARKET_ID}"
}
curl -X POST https://merchantapi.geins.io/graphql \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {JWT_TOKEN}" \
-H "X-ApiKey: {MERCHANT_API_KEY}" \
-d '{"query":"mutation acceptQuotation($quotationId: Guid!, $channelId: String, $languageId: String, $marketId: String) { acceptQuotation(quotationId: $quotationId, channelId: $channelId, languageId: $languageId, marketId: $marketId) }","variables":{"quotationId":"{QUOTATION_ID}","channelId":"{CHANNEL_ID}","languageId":"{LANGUAGE_ID}","marketId":"{MARKET_ID}"}}'
channelId, languageId, and marketId arguments are optional and can be left out to use default values.Response example
200 OK{
"data": {
"acceptQuotation": true
}
}
Reject a quotation
If the buyer does not agree with the terms, call rejectQuotation. The status changes to REJECTED and cannot be acted upon further.
Request example
mutation rejectQuotation(
$quotationId: Guid!
$channelId: String
$languageId: String
$marketId: String
) {
rejectQuotation(
quotationId: $quotationId
channelId: $channelId
languageId: $languageId
marketId: $marketId
)
}
{
"Accept": "application/json",
"Authorization": "Bearer {JWT_TOKEN}",
"X-ApiKey": "{MERCHANT_API_KEY}"
}
{
"quotationId": "{QUOTATION_ID}",
"channelId": "{CHANNEL_ID}",
"languageId": "{LANGUAGE_ID}",
"marketId": "{MARKET_ID}"
}
curl -X POST https://merchantapi.geins.io/graphql \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {JWT_TOKEN}" \
-H "X-ApiKey: {MERCHANT_API_KEY}" \
-d '{"query":"mutation rejectQuotation($quotationId: Guid!, $channelId: String, $languageId: String, $marketId: String) { rejectQuotation(quotationId: $quotationId, channelId: $channelId, languageId: $languageId, marketId: $marketId) }","variables":{"quotationId":"{QUOTATION_ID}","channelId":"{CHANNEL_ID}","languageId":"{LANGUAGE_ID}","marketId":"{MARKET_ID}"}}'
Response example
200 OK{
"data": {
"rejectQuotation": true
}
}
Finalize the quotation into an order
Once the quotation has been confirmed (status CONFIRMED) and isBlockedFromCheckout is false, call finalizeQuotation to place the order. Either the buyer or the seller can perform this step.
Request example
mutation finalizeQuotation(
$quotationId: Guid!
$channelId: String
$languageId: String
$marketId: String
) {
finalizeQuotation(
quotationId: $quotationId
channelId: $channelId
languageId: $languageId
marketId: $marketId
)
}
{
"Accept": "application/json",
"Authorization": "Bearer {JWT_TOKEN}",
"X-ApiKey": "{MERCHANT_API_KEY}"
}
{
"quotationId": "{QUOTATION_ID}",
"channelId": "{CHANNEL_ID}",
"languageId": "{LANGUAGE_ID}",
"marketId": "{MARKET_ID}"
}
curl -X POST https://merchantapi.geins.io/graphql \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {JWT_TOKEN}" \
-H "X-ApiKey: {MERCHANT_API_KEY}" \
-d '{"query":"mutation finalizeQuotation($quotationId: Guid!, $channelId: String, $languageId: String, $marketId: String) { finalizeQuotation(quotationId: $quotationId, channelId: $channelId, languageId: $languageId, marketId: $marketId) }","variables":{"quotationId":"{QUOTATION_ID}","channelId":"{CHANNEL_ID}","languageId":"{LANGUAGE_ID}","marketId":"{MARKET_ID}"}}'
Response example
200 OK{
"data": {
"finalizeQuotation": true
}
}
After finalization, retrieve the quotation cart to get the orderId:
query getQuotationCart($quotationId: Guid!) {
getQuotationCart(quotationId: $quotationId) {
quotation {
status
orderId
}
}
}
{
"data": {
"getQuotationCart": {
"quotation": {
"status": "FINALIZED",
"orderId": "12345"
}
}
}
}
Options
Multi-market support
All mutations support optional parameters for multi-market configurations:
channelId: Target specific sales channelslanguageId: Set content languagemarketId: Target specific markets
channelId, languageId, and marketId in the "how to"-article about using multi-market support.Authenticated access
These mutations require JWT authentication. Include the JWT bearer token in the Authorization header:
"Authorization": "Bearer {JWT_TOKEN}"
Common pitfalls
- Calling
finalizeQuotationwhenisBlockedFromCheckoutistruewill fail — the seller must confirm the quotation first whensettings.requireConfirmationistrue - Accepting or finalizing an expired quotation (past
validTo) will fail - Once a quotation is
REJECTED,FINALIZED, orCANCELED, no further status transitions are possible - Do not use
placeOrderon a quotation cart — usefinalizeQuotationinstead
Related docs
- Read quotations: Get quotation carts
- Cart basics: Get cart
- Standard checkout: Checkout headless cart
Filter products
Filter products using facets with includeMode and filterMode. Learn to build faceted navigation with parameters, categories, and brands using Geins Merchant API
Get brands
Retrieve all available brands for displaying brand navigation, filters, or brand listing pages using Geins Merchant API