Migrating from v2

If you report your loan book to Sivo v2 (DaaS), moving that integration to v3 is mostly a change of paths and a handful of field names. The flow is the same three steps, with more general names, because v3 covers any receivable and not only loans:

v2v3
Borrower (consumer or business)Account
LoanReceivable
ReportReceivable entry

Everything else carries over: amounts are still integers in the currency's smallest denomination (Money), dates and durations like "1 month" keep their format (Dates and Times), and every write is still an upsert keyed by an id you assign. Keep the ids you use in v2.

Endpoints

v2v3
POST /v1/borrowers/consumersPOST /accounts with type: "individual"
POST /v1/borrowers/businessesPOST /accounts with type: "business"
POST /v1/loansPOST /receivables
POST /v1/reportsPOST /receivables/{id}/entries

A few things also change around the requests:

  • Base URL. All v3 requests go to https://core.sivo.com, with no version prefix. Sandbox and live share this URL; the API key you send picks the environment (see Testing).
  • Authentication. v3 replaces the OAuth2 refresh/access token exchange with an API key from the developer dashboard, sent as the Authorization header on every request (Authorization: sk_live_...; see Authentication). There is no access token to fetch or refresh.
  • Partial updates. When you upsert an id that already exists, you only need to send the fields that changed (see Updating Data).
  • Retries. POST requests accept an IdempotencyKey header so you can retry safely (see Idempotent Requests).

Borrowers → accounts

Consumer and business borrowers become one account resource, told apart by type.

v2 fieldv3 fieldNotes
ididUnchanged.
—typeNew and required: individual for a consumer borrower, business for a business borrower.
first_name, last_namesame namesUnchanged.
companynameBusinesses: the business name.
entity_document_idlegal_entity_idPrefixed with the kind of id: rfc:ABC123456XYZ for a Mexican RFC, ein:123456789 for a US EIN (digits only, no dash), nit:900123456 for a Colombian NIT (the base number without dots or the check digit), nit:1020703023 for a Bolivian NIT, nif:B12345674 for a Spanish NIF, crn:08572260 for a UK Companies House number and bn:123456782 for a Canadian Business Number. A national id must match the account's address country (a nit: needs a CO or BO address); duns: works anywhere. An EIN must start with a prefix the IRS assigns, so a mistyped one like 17-4464132 is rejected. Each legal entity id can belong to only one of your accounts: if v2 has the same company twice, or several locations under one EIN, report them as one account, or send the id on one account only. Omit it when you don't have the id yet instead of sending a placeholder like PENDING.
address.streetaddress.street_address
address.cityaddress.locality
address.stateaddress.region
address.postal_code, address.countrysame namesUnchanged.
country_code, phonephoneOne field in E.164 format: a +, the country code, then the number. country_code: "57" and phone: "3001234567" become "+573001234567".
credit_rankingcredit_scorePrefixed with the bureau and zero-padded to 3 digits, like experian:720, datacredito:720 (DataCrédito Experian, Colombia) or transunion:650. A bare score like "430" is rejected; if you don't know which bureau a score comes from, or it's your own internal score, omit it. Omit it too when the borrower has no score.
industryindustryA 6-digit NAICS code instead of a named category. See Industry codes below.
email, websitesame namesUnchanged, but now optional. A website is a domain, like https://acme.com, not a page URL like https://acme.com/locations/austin. Omit it when the borrower has none instead of sending your own website.
is_veteran, date_of_birth, date_of_incorporation—No longer collected; drop them from the request.

For example, this v2 business borrower:

{
  "id": "brw-1001",
  "company": "Acme Logistics LLC",
  "entity_document_id": "12-3456789",
  "date_of_incorporation": "2019-04-01",
  "address": { "street": "100 Main St", "city": "Austin", "state": "TX", "postal_code": "78701", "country": "US" },
  "country_code": "1",
  "phone": "5125550100",
  "email": "[email protected]",
  "website": "https://acme.com",
  "industry": "restaurants"
}

becomes this v3 account:

{
  "id": "brw-1001",
  "type": "business",
  "name": "Acme Logistics LLC",
  "legal_entity_id": "ein:123456789",
  "address": { "street_address": "100 Main St", "locality": "Austin", "region": "TX", "postal_code": "78701", "country": "US" },
  "phone": "+15125550100",
  "email": "[email protected]",
  "website": "https://acme.com",
  "industry": "722511"
}

Industry codes

Use this table to translate the v2 industry categories to NAICS codes. The codes are a reasonable default for each category; if you know a more precise code for a borrower, send that instead (NAICS search).

v2 industryv3 industryNAICS title
animal_farming_production112990All Other Animal Production
arts_entertainment711510Independent Artists, Writers, and Performers
auto_dealers441110New Car Dealers
bank_financial_institution522110Commercial Banking
beauty_or_barber_shops812112Beauty Salons (812111 for Barber Shops)
building_materials_hardware444180Other Building Material Dealers
computer_service_repair811210Electronic and Precision Equipment Repair and Maintenance
fitness_sports_centers713940Fitness and Recreational Sports Centers
health_services621999All Other Miscellaneous Ambulatory Health Care Services
industrial_commercial_machinery423830Industrial Machinery and Equipment Merchant Wholesalers
insurance524210Insurance Agencies and Brokerages
other_education_services611699All Other Miscellaneous Schools and Instruction
other_food_services722513Limited-Service Restaurants
other_manufacturing339999All Other Miscellaneous Manufacturing
other_professional_services541990All Other Professional, Scientific, and Technical Services
real_estate531210Offices of Real Estate Agents and Brokers
restaurants722511Full-Service Restaurants
retail459999All Other Miscellaneous Retailers
retail_jeweler_diamonds_gems_gold458310Jewelry Retailers
sports_teams_clubs711211Sports Teams and Clubs

Loans → receivables

v2 fieldv3 fieldNotes
ididUnchanged.
borrower_idobligor_idThe account that owes the receivable.
credit_typeproduct_typeSame values: term_loan, line_of_credit, buy_now_pay_later, and so on.
delinquent_daysdelinquent_sinceThe date the loan became delinquent (today's date minus delinquent_days). Unlike a day count it doesn't change while the loan stays delinquent, so you don't need to update the loan every day just to increment a counter. Send it together with a delinquent_amount greater than zero (see the rules below).
receivable_type—Removed; drop it from the request.
program—Removed. If you need to keep it with the receivable, send it in metadata, like "metadata": { "program": "1" } (see Metadata).
funded_by, fund_name, origination_date, currency, term, payment_frequency, interest_rate, credit_limit, origination_fee, periodic_fee, collateral, delinquent_amount, delinquent_timessame namesUnchanged.

v3 checks a few rules that v2 did not enforce, so a loan v2 accepted can be rejected with 400 Bad Request:

  • fund_name is required when funded_by is other, and must be omitted for sivo and balance_sheet.
  • delinquent_times must be greater than zero when delinquent_amount is.
  • delinquent_since is required when delinquent_amount is greater than zero, and must be empty otherwise. v2 accepted delinquent_days on its own; in v3, report how much is overdue along with when it became overdue.
  • payment_frequency cannot be longer than term.

When a receivable comes out of delinquency, set delinquent_since to null and delinquent_amount to 0. Send the null explicitly: an omitted field is left unchanged (see Updating Data).

Reports → receivable entries

The loan id moves from the body into the path, and the status field is renamed. Entry types keep the same values and meaning.

v2 fieldv3 fieldNotes
loan_idpath {id}POST /receivables/{id}/entries instead of a body field.
loan_statusreceivable_statusSame values: active, closed.
id, date, type, amount, balance, descriptionsame namesUnchanged.

A v2 report:

curl -X POST https://dev.sivo.com/v1/reports \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "rep-0001",
    "loan_id": "loan-1001",
    "date": "2026-08-01",
    "type": "disbursement",
    "amount": 250000,
    "balance": 250000,
    "loan_status": "active"
  }'

becomes this v3 receivable entry:

curl -X POST https://core.sivo.com/receivables/loan-1001/entries \
  -H "Authorization: $SIVO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "rep-0001",
    "date": "2026-08-01",
    "type": "disbursement",
    "amount": 250000,
    "balance": 250000,
    "receivable_status": "active"
  }'

You can now also remove an entry reported by mistake with DELETE /receivables/{id}/entries/{entry_id}. For the complete account → receivable → entry flow in v3, see the Submit receivables recipe.

Moving your history

v3 calculates your portfolio metrics from the full history of every receivable, just like v2. You don't need to resend the borrowers, loans and reports you already reported in v2: Sivo will help migrate that history to v3. Coordinate the cutover with your Sivo contact so the history is in place before you start sending new activity to v3, and keep the same ids so your new entries line up with the migrated receivables. The history is copied from a snapshot of v2, so once it is in v3, send new activity to v3 only: anything you keep reporting to v2 afterwards has to be migrated again.


Did this page help you?