Capvant

Deal status

The stages, the reason codes and the rules every channel applies when you tell us where a deal stands.

Every way you can tell us where a deal stands reads the same stage list and the same reason codes: the API, your private inbound link, a reply to the referral email and the Lender Hub. Pick one of them as your team's main channel and report every stage there, including funded. The Lender Hub board does not yet show what arrives through the other channels (see From the Lender Hub).

The stages

Report the stage as the deal moves on your side, in this order.

  • In progress: received, contacted, documents_requested, in_underwriting.
  • Offer: approved, offer_made, offer_accepted, contracts_sent, contracts_signed.
  • Final: funded, declined, not_proceeding, duplicate.
StageLabel
receivedReceived
contactedContacted
documents_requestedDocuments requested
in_underwritingIn underwriting
approvedApproved
offer_madeOffer made
offer_acceptedOffer accepted
contracts_sentContracts sent
contracts_signedContracts signed
fundedFunded
declinedDeclined
not_proceedingNot proceeding
duplicateDuplicate or existing customer

You do not have to report every stage. A deal can go from received straight to declined, and the stage you send last is the one the deal shows.

What each stage needs

A request that misses one of these is refused with 400 and a message that names the field and the values it accepts. Nothing is recorded.

  • declined (your credit decision) and not_proceeding (the client stopped) need a reason_code.
  • duplicate (you already have this business) implies duplicate_or_existing_customer; send no code, or that one.
  • reason_code other needs a reason_note in your own words.
  • funded needs the amount you funded: funded_amount on the API, amount on the inbound link.
  • A reason_code sent with any other stage is ignored. A reason_note may go with any stage.

The stage follows the reason when the reason belongs to the other side, so nobody tells a client that a lender declined them when they walked away themselves:

  • declined with merchant_withdrew, merchant_unresponsive or merchant_declined_offer is recorded as not_proceeding.
  • not_proceeding with one of your own reasons, such as insufficient_revenue, is recorded as declined.
  • duplicate_or_existing_customer with declined or not_proceeding is recorded as duplicate.
  • statements_insufficient, documents_missing and other fit either side and keep the stage you sent.

Reason codes

  • Your decision: insufficient_revenue, time_in_business, credit_score, adverse_history, affordability, existing_debt, negative_balance_days, industry, location_not_served, amount_out_of_range, pricing_not_viable, does_not_meet_criteria, no_business_bank_account, identity_or_fraud, invalid_lead.
  • Either side: statements_insufficient, documents_missing, other.
  • The client's: merchant_unresponsive, merchant_withdrew, merchant_declined_offer.
  • A duplicate: duplicate_or_existing_customer.
Reason codeLabel
insufficient_revenueRevenue too low
time_in_businessNot trading long enough
credit_scoreCredit score below threshold
adverse_historyAdverse history (defaults, CCJs, insolvency, liens)
affordabilityRepayments not affordable
existing_debtToo much existing debt or stacking
negative_balance_daysNegative days or returned payments
industryIndustry not funded
location_not_servedLocation or owner residency not served
amount_out_of_rangeAmount outside the lenderโ€™s range
pricing_not_viableCould not offer suitable pricing
does_not_meet_criteriaDoes not meet minimum criteria
statements_insufficientBank statements missing, too few or unreadable
no_business_bank_accountNo business bank account
documents_missingOther documents missing
identity_or_fraudIdentity not verified or fraud concern
invalid_leadContact details wrong or not a real business
merchant_unresponsiveClient did not respond
merchant_withdrewClient did not proceed
merchant_declined_offerClient turned down the offer
duplicate_or_existing_customerDuplicate or existing customer
otherOther (note required)

The reason decides what happens next. After declined or duplicate the request goes on to the other lenders it suits, unless the reason is identity_or_fraud or invalid_lead. After not_proceeding it does not: that was the client's decision.

The client and any referral partner never see your reason_note. The client is shown a neutral sentence for the reason code.

The earlier Hub codes are still accepted and recorded as the current ones: sector as industry, time_trading as time_in_business, documentation as documents_missing, pricing as pricing_not_viable.

By API

POST /deals/{ref}/status with your API key.

Shell
curl -X POST https://api.capvant.com/v1/deals/93A41205CE/status \
  -H "X-API-Key: $CAPVANT_API_KEY" -H "content-type: application/json" \
  -d '{
  "status": "declined",
  "reason_code": "insufficient_revenue",
  "reason_note": "Average monthly deposits under our 15k minimum."
}'

The answer is the deal, plus the stage and reason as recorded: lender_stage, lender_reason_code and lender_reason_note. lender_stage can differ from the status you sent when the reason belongs to the other side. GET /deals and GET /deals/{ref} carry the coarse lender_status only, so keep this answer if you need the stage later.

  • stage is accepted in place of status, with the same values; when both are sent, stage wins.
  • Earlier values still work: in_review and in_progress are recorded as in_underwriting, offer as offer_made, withdrew as not_proceeding with merchant_withdrew, lost_on_terms as not_proceeding with merchant_declined_offer.
  • Every accepted change fires deal.updated to the endpoints you registered for it.

The free-text reason is deprecated

The earlier reason field still works for one release when no reason_code is sent: we read the code from your words, record other when nothing fits, and keep the text as the note. The answer then carries Deprecation: true and a Link header pointing at this page. Send reason_code, with reason_note for your own words.

The link on your Lender Hub integration page, https://api.capvant.com/v1/inbound/status/ followed by your secret, takes the same stages and reason codes with nothing to authenticate: the secret is the credential, so keep it out of shared documents and rotate it in the Hub if it leaks.

Shell
curl -X POST "$CAPVANT_INBOUND_URL" \
  -H "content-type: application/json" \
  -d '{"dealRef": "93A41205CE", "status": "funded", "amount": 85000}'
  • Find the deal with dealRef (our reference) or id (the lead id you returned when we created the lead). Either is enough.
  • status takes a stage, an earlier value or your own CRM stage name. Common names are understood as they are: "Working - Application Out" is documents_requested; "DNQ" and "Closed - Not Converted" are declined with does_not_meet_criteria; "Not a Lead" is declined with invalid_lead; "Deal Lost" is not_proceeding with merchant_declined_offer. Any other name can be mapped to a stage in the Lender Hub.
  • reason_code, or your own words in reason (we read the code from them). amount for funded.
  • The answer is { "ok": true, "dealRef": "93A41205CE", "status": "funded" }, where status is the stage recorded.

By email

Reply to the referral email with a short first line, for example "Funded ยฃ85,000" or "Declined: turnover below our minimum". Deals by email lists the phrases we record automatically; anything else is read and recorded by our team, so it shows later. Give the reason after a decline.

From the Lender Hub

The Hub board has five columns: New, In review, Offer made, Funded and Closed. Moving a deal to Closed asks for the reason, and moving it to Funded asks for the amount.

Every stage picked on the board reaches the deal itself, exactly like a status sent by API, the inbound link or email: Funded with its amount marks the deal funded, Closed records the reason. The other way round works too: a status reported by API, the inbound link or email moves the card on the board.

Errors you can meet

AnswerWhat it means
400, status is required: one of received, ...No status (or stage) in the body.
400, status "..." is not one of ...A value that is not a stage or an earlier value. On the inbound link: not a stage and not mapped in the Hub.
400, reason_code is required when status is declined: one of ...A decline or not proceeding without a code (and, on the inbound link, without words we can read one from).
400, reason_code "..." is not one of ...A code that is not in the list (and not an earlier Hub code).
400, reason_note is required when reason_code is other.other without a note.
400, funded_amount is required when status is funded.Funded without the amount, or funded_amount must be a positive number. for an amount that is not one.
404, not_foundNo deal routed to you has this reference (or, on the inbound link, this id).
401, unauthorizedA missing or revoked API key, or an unknown inbound secret.

The inbound link words a few of these differently, naming amount instead of funded_amount; the field and the rule are the same.

On this page