Skip to content
Logo

Accepting a quote

Once you have an AsyncQuoteSnapshot with status === "ready", check the selected quote's supporting-document requirement, then accept it to create an order.

Accept the best quote

Accepting takes a paymentReason (why the payment is being made — settlement networks require one). With just that, the snapshot's best_quote_id is used:

import {  } from "./client";
 
const  = await ..(, {
  : "purchase_of_goods",
});
// result: { id, status, source, destination, funding_instructions?, ... }

Picking a specific quote

To pick a specific entry from snapshot.quotes[], pass that entry's id to accept:

import {  } from "./client";
 
// `quoteId` is `snapshot.quotes[n].id`.
await ..(, "q_9e4d…", {
  : "purchase_of_goods",
});

The server returns 400 if quoteId isn't in the snapshot.

Compliance attachments

Some destination corridors require a document showing the purpose of the payment (an invoice, a salary stipend, or similar) before the payment can be settled. Read the selected quote's acceptance_requirements.files_required from a ready snapshot and collect a document before accepting when it is true. The field comes from the existing create/read quote responses; see Quote acceptance requirements.

The SDK permits the field to be absent for older servers, which means the requirement is unknown. Keep handling acceptRequiresFiles for a typed document-required rejection (field: "files", reason: "missing") and retry with files populated:

import {  } from "seismic-orchestration";
import {  } from "./client";
 
const  = await ..();
if (. !== "ready") {
  throw new ("Wait for a ready quote snapshot before accepting.");
}
 
const  = ..(() => . === .);
if (!) throw new ("No recommended quote is available.");
 
const  = .?.
  ? [{ : "invoice" as , : await () }]
  : ;
 
try {
  await ..(., ., {
    : "purchase_of_goods",
    ,
  });
} catch () {
  if (!()) throw ;
  await ..(., ., {
    : "purchase_of_goods",
    : [{ : "invoice", : await () }],
  });
}

The snapshot stays acceptable after the rejection, so the retry works as long as the quote hasn't expired. Attachment constraints and the full violation shape are in the accept reference.

Handling quote expiry

By default (refund_payment), a payment whose quote expired before your funds arrived is refunded. Some quotes can instead re-quote at the market rate and settle, letting either the destination amount (flexible_destination_amount) or the source amount (flexible_source_amount) move with it. Each quote lists what it supports in supported_expired_quote_behaviors. Choose at accept time with expiredQuoteBehavior:

import {  } from "./client";
 
const  = await ..();
const  = .[0];
 
if (
  ..(
    "flexible_destination_amount",
  )
) {
  await ..(, ., {
    : "purchase_of_services",
    : "flexible_destination_amount",
  });
}

Passing a behavior the quote doesn't support fails with a typed expired_quote_behavior violation. The full shape is in the accept reference.

Re-reading an order

When you already have the order id (from the accept response, a webhook, a deeplink), call api.customers.order(id) for the current state. For a feed of recent orders across the org, use api.customers.orders().

import {  } from "./client";
 
const orderArrow
= await ..();
const = await ..(); // Returns up to 200 rows, most-recent first.

An order's lifecycle (pending → submitted → settled / failed) updates the same row. There's no new row per state transition. Poll, or consume webhooks in a backend.

Canceling an order

An order that hasn't received funds yet — status still awaiting_funds or pending — can be canceled. The payment is canceled and the order is returned with status: "canceled". Its funding instructions stop being valid immediately.

import {  } from "./client";
 
const  = await ..();
// canceled.status === "canceled"

The canceled order comes back in the response itself — a cancellation you initiated doesn't fire an order.status_changed webhook.

Once the order is processing or later, it can no longer be canceled: the call fails with 409 Conflict (OrderNotCancelable), and the error body's status field carries the order's current state. Treat the 409 as "too late" and let the order play out.

Not every payment supports cancellation. When this one doesn't, the call fails with 400 (InvalidRequest). Details are in the cancel reference.

Idempotency

Accepting the same snapshot twice returns 409 Conflict: the first accept attaches the snapshot to an order. Subsequent accepts are rejected.

For retry-safety, store snapshot.id alongside your request before calling accept. On retry, re-read the snapshot and check whether it's already associated with an order.

End-to-end example

import { ,  } from "seismic-orchestration";
 
const  = .();
 
async function (
  : string,
  : string,
  : string,
) {
  const  = await ..(
    {
      : ,
      : "individual",
      : ,
      : { : "USD", : ["ach"] },
      : ,
    },
    { : true },
  );
 
  if (.. === 0) {
    throw new ("no options priced this corridor");
  }
 
  try {
    return await ..(., {
      : "purchase_of_goods",
    });
  } catch () {
    if ( instanceof  && . === 409) {
      // Already accepted: treat as success.
      return null;
    }
    throw ;
  }
}