Docs

Payments

New Sales API

Submit vehicle and home warranty sales with their payment plans, validated and booked in real time over HTTPS.

v1 https://api-sandbox.archcrm.com Updated 2026-10-07 Support: apisupport@archcrm.com

Introduction

The ArchPay New Sales API lets an authorized partner organization submit vehicle and home warranty sales (service contracts) with their payment plans, programmatically, over HTTPS.

Business objective. Replace manual / batch sale entry with a validated, real-time API so partner organizations can submit a sale, have it checked against Arch's business rules immediately, collect any due-now payment, and book the resulting contract. The API is the single front door for new-sale intake.

What the API does

  • Authenticates the calling organization with OAuth 2.0 client credentials.
  • Accepts a single sale (POST /v1/sales) or up to 100 sales in one call (POST /v1/sales/batch).
  • Validates each sale in stages: request format and cross-field structure, then identity and duplicate checks, then business math and date rules.
  • For payment plans that move money at sale time, charges the card through Arch's payment processor before the sale is booked.
  • Returns a precise, coded result for every sale, including warnings that do not block booking.

API Overview

Architecture styleREST over HTTPS. JSON request and response bodies (the token endpoint uses form-encoded input per the OAuth 2.0 spec).
Base URL (Sandbox)https://api-sandbox.archcrm.com — the partner test environment. Traffic passes through Azure API Management: every request must also carry the Ocp-Apim-Subscription-Key header issued during onboarding (a request without it is rejected 401 before reaching the API).
Base URL (Production)https://api.archcrm.com — same gateway rule as sandbox, with a separate production subscription key issued during onboarding.
VersioningURI path prefix /v1 on all functional endpoints.
AuthenticationOAuth 2.0 client_credentials grant; short-lived JWT bearer tokens. In sandbox and production, the gateway subscription key header on every request as well.
Transport securityHTTPS only (HTTP is rejected). Minimum TLS 1.2. HTTP/2 enabled.
Rate limitingSandbox and production: 120 requests per 60 seconds per organization (per subscription key), enforced at the API gateway. Exceeding it returns HTTP 429 with a gateway-generated body — back off until the window resets. Limits may be tuned per partner tier.
Content typeRequests: application/json (sales) or application/x-www-form-urlencoded (token). Responses: application/json.
Request size limit1 MB per request body. A larger request is rejected with HTTP 413 without being read.
Character encodingUTF-8 on the wire. Field values are restricted to standard Latin characters by the field constraints.

Endpoint summary

MethodPathAuthPurpose
POST/v1/oauth/tokenClient ID + secretObtain a bearer access token.
POST/v1/salesBearerSubmit one sale.
POST/v1/sales/batchBearerSubmit up to 100 sales (partial success).
GET/healthNoneLiveness/readiness probe (HEAD is also accepted, for uptime monitors).

Authentication & Authorization

Two credentials on every call Sandbox and production sit behind Azure API Management. Every request — including the token call and /health — must carry both:
  1. The gateway subscription key, in the Ocp-Apim-Subscription-Key header. Checked by the gateway before the request reaches the API.
  2. The OAuth bearer token, in the Authorization header (all /v1/sales* calls). Checked by the API itself.
They are separate: a valid token without the key is rejected at the gateway, and the key alone does not authorize any sale. See Gateway Subscription Key.

Mechanism

The API uses the OAuth 2.0 client credentials grant. Your organization is issued a client_id and client_secret. You exchange them at the token endpoint for a short-lived JWT access token, then send that token as a bearer credential on every sales request.

Note Client credentials and sandbox test credentials are provisioned by the Arch team. There is no self-service flow.

Obtaining a token

Send a form-encoded POST to /v1/oauth/token:

ParameterInRequiredValue
Ocp-Apim-Subscription-KeyheaderYesYour gateway subscription key for this environment. See Gateway Subscription Key.
grant_typeform bodyYesMust be client_credentials.
client_idform bodyYesYour organization's client identifier (opaque string).
client_secretform bodyYesYour organization's client secret.

Example request

curl -X POST https://api-sandbox.archcrm.com/v1/oauth/token \
  -H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

Success response (HTTP 200)

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 1800
}
access_tokenJWT signed with HS256. Treat it as an opaque string; do not parse or depend on its claims.
token_typeAlways Bearer.
expires_inToken lifetime in seconds. Currently 1800 (30 minutes).

Using the token

Send the token in the Authorization header on every call to /v1/sales and /v1/sales/batch:

Authorization: Bearer {access_token}

In sandbox and production, every request additionally carries the Ocp-Apim-Subscription-Key header issued during onboarding, one key per environment (see API Overview).

A missing, malformed, expired, or otherwise invalid token is answered with HTTP 401, header WWW-Authenticate: Bearer, and the body {"status":"rejected","requestId":"...","error":"invalid_token"}.

Token lifecycle

  • Lifetime: 30 minutes. There is no refresh token in the client-credentials grant; request a new token when the current one nears expiry.
  • Caching: reuse a token until it is close to expiring rather than minting one per request.
  • Revocation: tokens are not individually revocable and there is no introspection endpoint. Deactivating a client stops new tokens from being issued; an already-issued token remains valid until it expires. The short lifetime bounds exposure.

Authorization model (organization → producers)

Your token represents your organization (an Arch tenant), not an individual producer. An organization owns one or more producer codes. Every sale names a producerCode, and the API verifies that the named producer is authorized for your organization. A sale that uses a producer code not mapped to your organization is rejected with 50009 PRODUCER_NOT_AUTHORIZED.

Note Producer codes are shared across organizations — a producer code by itself does not identify an organization. Authorization is always evaluated against the organization in your token.

Security considerations

  • Store the client_secret in a secret manager; never embed it in client-side code or commit it to source control.
  • All traffic must use HTTPS (TLS 1.2+). Plain HTTP is refused.
  • Secrets are stored by Arch as salted PBKDF2-SHA256 hashes; they cannot be recovered, only reset.
  • Card data is passed through to the payment processor and tokenized (vaulted); ArchPay does not store raw PANs. CVV is not collected.
  • Treat the gateway subscription key like a secret too: keep it server-side, never in browser or mobile code.

Gateway Subscription Key

Sandbox and production traffic enters through Azure API Management (the API gateway). The gateway admits only requests that carry a valid subscription key.

HeaderOcp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY
Required onEvery request: POST /v1/oauth/token, POST /v1/sales, POST /v1/sales/batch, and GET/HEAD /health.
Issued byThe Arch team during onboarding, together with your OAuth client credentials. There is no self-service flow.
Per environmentOne key for sandbox, a different key for production. A sandbox key does not work against production.
Primary / secondaryEach subscription has two keys; either one is accepted. Use the second key to rotate without downtime: switch your systems to it, then ask Arch to regenerate the first.
What it doesAdmits and meters your traffic (120 requests per 60 seconds, 1 MB body). It does not identify your organization for authorization — that is the OAuth token's job.

Gateway responses

These come from the gateway, not the API, so their body shape differs from the API's {"status":"rejected",...} envelope and they carry no requestId.

StatusWhenExample body
401The Ocp-Apim-Subscription-Key header is missing.{"statusCode":401,"message":"Access denied due to missing subscription key. ..."}
401The key is wrong, regenerated, for the other environment, or the subscription is suspended.{"statusCode":401,"message":"Access denied due to invalid subscription key. ..."}
429More than 120 requests in 60 seconds on this key.{"statusCode":429,"message":"Rate limit is exceeded. Try again in N seconds."}
Tell the 401s apart A 401 with statusCode in the body is the gateway (check the subscription key). A 401 with "error":"invalid_token" and a WWW-Authenticate: Bearer header is the API (get a new bearer token).

POST /v1/oauth/token

Exchanges client credentials for a bearer access token. See Authentication for the parameter table and a request/response example.

Responses

StatusBodyWhen
200{access_token, token_type, expires_in}Credentials valid.
401{"statusCode":401,"message":"..."}Gateway: subscription key missing or invalid. See Gateway Subscription Key.
400{"error":"unsupported_grant_type"}grant_type is not client_credentials.
401{"error":"invalid_client"}Unknown client, inactive client, or wrong secret.
422{"status":"rejected","requestId":"...","errors":[{"code":50012,...}]}A required form field is missing or the body is malformed.
503{"error":"temporarily_unavailable"}The credential store is unreachable; no token was issued. Retry later.
Note The token endpoint returns two error shapes: the OAuth {"error":...} object for credential and availability problems, and the coded {"status":"rejected",...} envelope for a missing form field.

POST /v1/sales

Purpose. Submit a single sale for validation, payment (if due now), and booking.

Request

WhereNameRequiredNotes
HeaderOcp-Apim-Subscription-KeyYesGateway subscription key. See Gateway Subscription Key.
HeaderAuthorizationYesBearer {access_token}
HeaderContent-TypeYesapplication/json
BodySale objectYesA single sale. Full schema in Data Models.

Example request (Auto, financed / NonMTM, paid by card)

curl -X POST https://api-sandbox.archcrm.com/v1/sales \
  -H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json" \
  -d '{
  "sale": {
    "saleType": 2,
    "contractNumber": "H612718768",
    "producerCode": 3046,
    "administratorCode": 1002,
    "insuranceCarrierCode": 2010,
    "saleDate": "2026-06-10"
  },
  "coverage": {
    "termMonths": 60,
    "effectiveDate": "2026-06-15",
    "expirationDate": "2031-06-15",
    "administratorCost": 955.00
  },
  "vehicle": {
    "vin": "1HGCM82633A004352",
    "year": 2019, "make": "Honda", "model": "Accord",
    "termMiles": 36000, "saleOdometer": 42500,
    "effectiveOdometer": 42500, "expiryOdometer": 78500
  },
  "primaryContractHolder": {
    "firstName": "Jane", "lastName": "Doe",
    "phone": "3125551212", "email": "jane@example.com", "preferredLanguage": 1
  },
  "addresses": {
    "mailing":  {"line1":"33 W Delaware Pl","line2":"Apt 6A","city":"Chicago","state":"IL","zipCode":"60610"},
    "billing":  {"line1":"33 W Delaware Pl","city":"Chicago","state":"IL","zipCode":"60610"}
  },
  "paymentPlan": {
    "retailCost": 4000.00, "downPayment": 200.00,
    "downPaymentProcessMethod": 1, "startingBalance": 3800.00,
    "installmentStartDate": "2026-07-01", "billingCycle": 1,
    "numberOfInstallments": 24, "installmentAmount": 158.33,
    "paymentMethod": 1
  },
  "paymentInstrument": {
    "card": {"holderName":"Jane Doe","number":"4111111111111111","expiration":"08/2028"}
  }
}'

Success response

201 Created A sale that passes every check returns:

{
  "status": "accepted",
  "requestId": "a1b2c3d4e5f6a7b8",
  "contractId": 90432,
  "contractNumber": "H612718768",
  "warnings": []
}

contractId is Arch's internal contract identifier; contractNumber is your key echoed back; requestId is an Arch-generated correlation id (present on every response). No payment / charge-receipt object is returned: when a due-now (FinCo) card charge is taken, it is reconciled out of band — the success envelope carries exactly the five fields above.

Rejection responses

StatusBody shapeWhen
422{"status":"rejected","requestId":"...","contractNumber":"...","errors":[{code,field,message}],"warnings":[...]}One or more validation rules failed (format, identity/duplicate, business/pricing, or payment input), the card charge was declined (60302), or a due-now charge is owed but the producer has no processor / processor key configured (60306, 60307).
401{"status":"rejected","requestId":"...","error":"invalid_token"}Missing, malformed, expired, or invalid bearer token. Returns header WWW-Authenticate: Bearer.
401{"statusCode":401,"message":"..."}Gateway: subscription key missing or invalid. See Gateway Subscription Key.
429{"statusCode":429,"message":"..."}Gateway: rate limit exceeded. Back off until the window resets.
413{"status":"rejected","requestId":"...","error":"request body too large"}The request body exceeds the 1 MB cap. Nothing was processed.
500{"status":"rejected","requestId":"...","errors":[{"code":60303|60304|60305,...}]}Booking failed. 60303: the charge was reversed, safe to resubmit. 60304: the reversal also failed — do not blindly resubmit; contact Arch. 60305: nothing was charged, safe to resubmit.
502{"status":"rejected","requestId":"...","errors":[{"code":60301,...}]}The payment processor was unavailable; the sale was not booked. Safe to retry later.
503{"status":"error","requestId":"...","message":"sale validation is unavailable; the sale was not processed"}A required backend dependency is down. Retry later.

Example rejection (HTTP 422)

{
  "status": "rejected",
  "requestId": "a1b2c3d4e5f6a7b8",
  "contractNumber": "H612718768",
  "errors": [
    {"code": 50117, "field": "addresses.mailing.zipCode", "message": "must be 5 digits"},
    {"code": 50207, "field": "paymentPlan.startingBalance", "message": "must equal retailCost minus downPayment"}
  ],
  "warnings": []
}

contractNumber is echoed back on rejections too (normalized); it is null when the body was unreadable.

All independent violations found in one pass are returned together so they can be fixed in a single round trip. See the Error Catalog for validation ordering and every code.

POST /v1/sales/batch

Purpose. Submit 1 to 100 sales in one call. Each row is validated, charged, and booked independently (partial success): one bad row never blocks its neighbors.

Request headers

Same as /v1/sales: Ocp-Apim-Subscription-Key, Authorization: Bearer {access_token}, and Content-Type: application/json.

Request body

{ "sales": [ { /* sale object */ }, { /* sale object */ } ] }
FieldRequiredConstraint
salesYesArray of sale objects (same schema as /v1/sales). Minimum 1, maximum 100.

Success response (HTTP 200)

{
  "requestId": "a1b2c3d4e5f6a7b8",
  "summary": { "submitted": 2, "accepted": 1, "rejected": 1 },
  "results": [
    {"index": 0, "contractNumber": "H612718768", "status": "accepted", "contractId": 90432, "errors": [], "warnings": []},
    {"index": 1, "contractNumber": "H612718768", "status": "rejected", "errors": [ ... ], "warnings": []}
  ]
}

HTTP status semantics

StatusMeaning
200The batch was processed. Inspect each row's status and errors — rows can individually be rejected even though the HTTP status is 200. This is deliberate: a 4xx would invite a blind retry that re-submits already-booked rows.
422The whole request failed before any row was processed: empty array (50011), more than 100 rows (50010), or a malformed body (50012).
401Missing or invalid bearer token, or (gateway) missing or invalid subscription key.
429Gateway rate limit exceeded; nothing was processed.
413The request body exceeds the 1 MB cap; nothing was processed.
503A required backend dependency is down; nothing was processed.
In-batch duplicates Within one batch, the first row that books with a given contractNumber claims it; any later row with the same number is rejected with 50008, citing the earlier row's index. A row that was itself rejected does not claim its number — a later row may still book it.

GET /health

Purpose. Liveness/readiness probe; no OAuth bearer token is required. Note: no /v1 prefix. HEAD /health is also accepted (same status, empty body) for uptime monitors. The gateway subscription key is still required — a keyless request is rejected 401 at the gateway.

GET https://api-sandbox.archcrm.com/health
Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY

200 OK
{ "status": "ok", "environment": "sandbox" }

Data Models & Enums

The sale request is a single JSON object with nested sections. Field names are camelCase. Unknown fields are rejected (a typo'd field name is an error — 50101), not ignored. Strings are trimmed. Money fields are decimals with at most 2 decimal places (and at most 12 digits in total); send them as JSON numbers (for example 955.00).

Top-level structure

SectionRequiredNotes
saleYesIdentity of the sale.
coverageYesTerm, dates, administrator cost.
vehicleConditionalRequired for Auto sales; must be omitted for Home sales.
propertyConditionalRequired for Home sales; must be omitted for Auto sales.
primaryContractHolderYesThe customer.
addressesYesmailing + billing always; property only for Home.
paymentPlanYesMoney and schedule.
paymentInstrumentConditionalRequired for Card/ACH; must be omitted for Invoice.

The sale type drives everything

saleType selects the product family (Auto vs Home) and the financing style (MTM vs NonMTM), which in turn decide which sections and fields are required or forbidden.

  • MTM (Month-to-Month): a recurring plan with an activationFee; the financed-purchase fields are not used.
  • NonMTM (Financed / Termed): a retail cost financed over a fixed number of installments, with a derived starting balance.
saleTypeMeaningvehiclepropertyMoney fields
1Auto, MTMRequiredForbiddenActivation set
2Auto, NonMTMRequiredForbiddenFinanced set
3Home, MTMForbiddenRequiredActivation set
4Home, NonMTMForbiddenRequiredFinanced set

Conditional field matrix

Rule groupDiscriminatorRequiredForbidden
ItemAuto (1,2)vehicle, vehicle.saleOdometerproperty, addresses.property
ItemHome (3,4)property, addresses.propertyvehicle
MileageAuto NonMTM (2)termMiles, effectiveOdometer, expiryOdometer—
MoneyMTM (1,3)activationFee, activationFeeProcessMethodretailCost, downPayment, downPaymentProcessMethod, startingBalance, numberOfInstallments, termMonths
MoneyNonMTM (2,4)retailCost, downPayment, downPaymentProcessMethod, startingBalance, numberOfInstallments, termMonthsactivationFee, activationFeeProcessMethod
PropertypropertyType = 2 (Multi Unit)unitCount—
PropertypropertyType ≠ 2—unitCount
InstrumentpaymentMethod = 1 (Card)cardbank
InstrumentpaymentMethod = 2 (ACH)bankcard
InstrumentpaymentMethod = 3 (Invoice)—card, bank

Field reference

sale

FieldTypeRequiredConstraint
saleTypeintegerYes1–4.
contractNumberstringYes1–25 chars. Normalized to UPPERCASE with spaces removed before the duplicate check.
producerCodeintegerYes3000–3999.
administratorCodeintegerYes1000–1999.
insuranceCarrierCodeintegerNo2000–2999 when present.
saleDatedate (YYYY-MM-DD)YesNot in the future.

coverage

FieldTypeRequiredConstraint
termMonthsintegerNonMTM only> 1 and ≤ 120. Forbidden for MTM.
effectiveDatedateYesNot backdated more than 30 days.
expirationDatedateNoOptional; when omitted, it is derived at booking.
administratorCostdecimalYes≥ 0, 2 dp. For NonMTM, must not exceed retailCost.

vehicle (Auto sales)

FieldTypeRequiredConstraint
vinstringYes17 characters, excludes I/O/Q; upper-cased automatically. The ISO-3779 check digit (9th character) must match (50161).
yearintegerYes1980–2099.
makestringYes1–50 chars; cannot contain #.
modelstringYes1–100 chars; cannot contain #.
saleOdometerintegerAll Auto≥ 0.
termMilesintegerAuto NonMTM> 0.
effectiveOdometerintegerAuto NonMTM≥ 0.
expiryOdometerintegerAuto NonMTM≥ 0.

property (Home sales)

FieldTypeRequiredConstraint
propertyTypeintegerYes1 Single Family, 2 Multi Unit, 3 Condo.
unitCountintegerpropertyType = 22–4. Forbidden otherwise.
yearBuiltintegerNo1800 – current year.
squareFootageintegerNo1–32000.

primaryContractHolder

FieldTypeRequiredConstraint
firstNamestringYes1–30 chars.
lastNamestringYes1–30 chars.
phonestringYes10-digit US number or E.164 (optional leading +, 10–15 digits).
emailstringNoValid email, ≤ 100 chars.
preferredLanguageintegerNo1 English, 2 Spanish.

addresses and the address shape

Each address slot (property, mailing, billing) has the same shape. mailing and billing are always required. property is required for Home sales and forbidden for Auto sales.

FieldTypeRequiredConstraint
line1stringYes1–255 chars.
line2stringNoOptional; ≤ 255 chars.
citystringYes1–50 chars.
statestringYes2-letter code; must be a real US state or territory (USPS list: 50 states, DC, AS/GU/MP/PR/VI, AA/AE/AP). An unknown code such as ZZ is rejected.
zipCodestringYesExactly 5 digits.

paymentPlan

FieldTypeRequiredConstraint
retailCostdecimalNonMTM> 0, 2 dp.
downPaymentdecimalNonMTM≥ 0, 2 dp.
downPaymentProcessMethodintegerNonMTM1–3.
startingBalancedecimalNonMTM> 0, 2 dp. Must equal retailCost - downPayment.
numberOfInstallmentsintegerNonMTM≥ 1.
activationFeedecimalMTM≥ 0, 2 dp.
activationFeeProcessMethodintegerMTM1–3.
installmentStartDatedateYesDay of month 1–28; on or after effectiveDate.
billingCycleintegerYesMust be 1 (Monthly).
installmentAmountdecimalYes> 0, 2 dp. For NonMTM, must equal startingBalance / numberOfInstallments within $0.01.
paymentMethodintegerYes1 Card, 2 ACH, 3 Invoice.

paymentInstrument

Provide card for Card payments, bank for ACH, neither for Invoice. Providing both, or the wrong one, is rejected.

Object.FieldTypeConstraint
card.holderNamestring1–50 chars.
card.numberstring15–16 digits; must pass the Luhn checksum (50315). Still subject to processor acceptance.
card.expirationstringMM/YYYY. The card must not be expired: an expiration month earlier than the current month (US Central) is rejected at the business stage (50313). A card is accepted through the last day of its expiration month.
bank.accountTypeinteger1 Checking, 2 Savings.
bank.routingNumberstring9 digits (ABA); must pass the ABA checksum (50316).
bank.accountNumberstring6–17 digits.

Card security codes (CVV) are not collected and are not part of the request.

Enumerations

Enum (field)ValueMeaning
saleType1Auto, MTM (Month-to-Month)
2Auto, NonMTM (Financed)
3Home, MTM
4Home, NonMTM
propertyType1Single Family
2Multi Unit (requires unitCount)
3Condo
paymentMethod1Card
2ACH (bank)
3Invoice (no instrument)
downPaymentProcessMethod / activationFeeProcessMethod1Producer / PMA — producer-managed; ArchPay does not charge at sale time.
2Producer / FinMA — producer-managed; ArchPay does not charge at sale time.
3FinCo / FinMA — ArchPay charges this amount now. Card only.
preferredLanguage1English
2Spanish
bank.accountType1Checking
2Savings
billingCycle1Monthly (only accepted value)

Response objects

Error / warning item

codeinteger — the catalog code, or null for an uncoded type error.
fieldstring — dotted path to the offending field (e.g. addresses.mailing.zipCode), or null.
messagestring — human-readable description.
Note Every response carries a requestId (including 401, 413, and 503) — quote it when contacting support. No payment / charge-receipt object is returned: when a due-now (FinCo) card charge is taken, it is reconciled out of band, and a declined charge rejects the sale (60302).

Error Handling & Code Catalog

Validation order

A sale is checked in stages. Format and structure are checked first; if they fail, the later stages do not run. Within a stage, all violations are collected and returned together.

StageCode rangeWhat it checks
Request / batch meta50010–50012Batch size, malformed body.
Format & structure50101–50120, 50122, 50125–50161Field types, ranges, patterns, checksums (VIN/Luhn/ABA), required/forbidden sections per sale type.
Identity & duplicate50001–50009, 50013Producer/administrator/carrier exist, are active, are authorized; duplicate contract number.
Business math, dates & pricing50121, 50123–50124, 50201–50216, 50313, 51600, 60101Money relationships, date rules (judged on US Central time), card expiry, and the producer discount-fee pricing check.
Payment & booking50301–50316, 60301–60307Instrument format, processor configuration, charge outcome, booking outcome.

Errors vs warnings

  • Errors reject the sale (or batch row). Fix the input and resubmit.
  • Warnings do not block booking; they ride along in the warnings array. Only 60101 (SALE_DATE_STALE) is currently emitted; 60102 (ADDRESS_UNVERIFIED) is reserved for a future release.

Full code catalog

HTTP status is 422 unless noted. Search by number, name, field, or message; filter by stage. Links elsewhere in this guide jump straight to a code below.

All Request & Identity Format Business & Dates Payment Warnings & Outcomes
CodeNameHTTPFieldMessage
50001PRODUCER_NOT_FOUND422sale.producerCodeproducer not found
50002ADMIN_NOT_FOUND422sale.administratorCodeadministrator not found
50003SALETYPE_INVALID422sale.saleTypemust be 1, 2, 3 or 4
50004CARRIER_NOT_FOUND422sale.insuranceCarrierCodeinsurance carrier not found
50005PRODUCER_INACTIVE422sale.producerCodeproducer is not active
50006ADMIN_INACTIVE422sale.administratorCodeadministrator is not active
50007SALETYPE_PRODUCER_MISMATCH422sale.saleTypesaleType does not match the producer portfolio
50008DUPLICATE_CONTRACT_NUMBER422sale.contractNumbercontract number already exists
50009PRODUCER_NOT_AUTHORIZED422sale.producerCodeproducer is not authorized for the calling organization
50010BATCH_TOO_LARGE422salesbatch exceeds maximum of 100 sales
50011BATCH_EMPTY422salesbatch must contain at least 1 sale
50012MALFORMED_REQUEST422(body)request body is malformed
50013CARRIER_INACTIVE422sale.insuranceCarrierCodeinsurance carrier is not active
50101UNKNOWN_FIELD422(varies)unknown field
50102CONTRACT_NUMBER_CONSTRAINT422sale.contractNumbermust be 1-25 characters
50103PRODUCER_CODE_CONSTRAINT422sale.producerCodemust be between 3000 and 3999
50104ADMIN_CODE_CONSTRAINT422sale.administratorCodemust be between 1000 and 1999
50105CARRIER_CODE_CONSTRAINT422sale.insuranceCarrierCodemust be between 2000 and 2999
50106ADMIN_COST_CONSTRAINT422coverage.administratorCostmust be 0 or more with at most 2 decimals
50107FIRST_NAME_CONSTRAINT422primaryContractHolder.firstNamemust be 1-30 characters
50108LAST_NAME_CONSTRAINT422primaryContractHolder.lastNamemust be 1-30 characters
50109PHONE_CONSTRAINT422primaryContractHolder.phonemust be a 10-digit US number or E.164
50110EMAIL_CONSTRAINT422primaryContractHolder.emailmust be a valid email of at most 100 characters
50111PREFERRED_LANGUAGE_CONSTRAINT422primaryContractHolder.preferredLanguagemust be 1 or 2
50112BILLING_CYCLE_CONSTRAINT422paymentPlan.billingCyclemust be 1 (Monthly)
50113INSTALLMENT_AMOUNT_CONSTRAINT422paymentPlan.installmentAmountmust be greater than 0 with at most 2 decimals
50114PAYMENT_METHOD_CONSTRAINT422paymentPlan.paymentMethodmust be 1, 2 or 3
50115MAILING_LINE1_CONSTRAINT422addresses.mailing.line1must not be empty
50116MAILING_STATE_CONSTRAINT422addresses.mailing.statemust be a 2-letter state code
50117MAILING_ZIP_CONSTRAINT422addresses.mailing.zipCodemust be 5 digits
50118BILLING_LINE1_CONSTRAINT422addresses.billing.line1must not be empty
50119BILLING_STATE_CONSTRAINT422addresses.billing.statemust be a 2-letter state code
50120BILLING_ZIP_CONSTRAINT422addresses.billing.zipCodemust be 5 digits
50121SALE_DATE_FUTURE422sale.saleDatemust not be in the future
50122INSTALLMENT_DAY_INVALID422paymentPlan.installmentStartDateday of month must be 1-28
50123INSTALLMENT_START_BEFORE_EFFECTIVE422paymentPlan.installmentStartDatemust be on or after the effective date
50124EFFECTIVE_DATE_BACKDATED422coverage.effectiveDatemust not be more than 30 days in the past
50125MAILING_ADDRESS_REQUIRED422addresses.mailingmailing address is required
50126BILLING_ADDRESS_REQUIRED422addresses.billingbilling address is required
50127VIN_CONSTRAINT422vehicle.vinmust be 17 characters excluding I, O and Q
50128VEHICLE_YEAR_CONSTRAINT422vehicle.yearmust be between 1980 and 2099
50129MAKE_MODEL_CONSTRAINT422vehicle.make / vehicle.modelmust not be empty and must not contain #
50130VEHICLE_REQUIRED422vehiclevehicle is required for Auto sales
50131PROPERTY_REQUIRED422propertyproperty is required for Home sales
50132SALE_ODOMETER_REQUIRED422vehicle.saleOdometerrequired for Auto sales
50133TERM_MILES_REQUIRED422vehicle.termMilesrequired for Auto NonMTM sales
50134EFFECTIVE_ODOMETER_REQUIRED422vehicle.effectiveOdometerrequired for Auto NonMTM sales
50135EXPIRY_ODOMETER_REQUIRED422vehicle.expiryOdometerrequired for Auto NonMTM sales
50136PROPERTY_FORBIDDEN422propertymust be omitted for Auto sales
50137VEHICLE_FORBIDDEN422vehiclemust be omitted for Home sales
50138PROPERTY_TYPE_CONSTRAINT422property.propertyTypemust be 1, 2 or 3
50139UNIT_COUNT_CONSTRAINT422property.unitCountmust be between 2 and 4
50140YEAR_BUILT_CONSTRAINT422property.yearBuiltmust be between 1800 and the current year
50141SQUARE_FOOTAGE_CONSTRAINT422property.squareFootagemust be between 1 and 32000
50142PROPERTY_ADDRESS_REQUIRED422addresses.propertyrequired for Home sales
50143PROPERTY_ADDRESS_FORBIDDEN422addresses.propertymust be omitted for Auto sales
50144UNIT_COUNT_REQUIRED422property.unitCountrequired when propertyType is Multi Unit
50145UNIT_COUNT_FORBIDDEN422property.unitCountmust be omitted unless propertyType is Multi Unit
50146SALE_DATE_CONSTRAINT422sale.saleDatemust be a valid date (YYYY-MM-DD)
50147EFFECTIVE_DATE_CONSTRAINT422coverage.effectiveDatemust be a valid date (YYYY-MM-DD)
50148EXPIRATION_DATE_CONSTRAINT422coverage.expirationDatemust be a valid date (YYYY-MM-DD)
50149MAILING_CITY_CONSTRAINT422addresses.mailing.citymust not be empty
50150BILLING_CITY_CONSTRAINT422addresses.billing.citymust not be empty
50151PROPERTY_LINE1_CONSTRAINT422addresses.property.line1must not be empty
50152PROPERTY_CITY_CONSTRAINT422addresses.property.citymust not be empty
50153PROPERTY_STATE_CONSTRAINT422addresses.property.statemust be a 2-letter state code
50154PROPERTY_ZIP_CONSTRAINT422addresses.property.zipCodemust be 5 digits
50155SECTION_REQUIRED422(varies)required top-level section is missing or invalid
50156TERM_MILES_CONSTRAINT422vehicle.termMilesmust be a positive number of miles
50157SALE_ODOMETER_CONSTRAINT422vehicle.saleOdometermust be a non-negative number of miles
50158EFFECTIVE_ODOMETER_CONSTRAINT422vehicle.effectiveOdometermust be a non-negative number of miles
50159EXPIRY_ODOMETER_CONSTRAINT422vehicle.expiryOdometermust be a non-negative number of miles
50160ACTIVATION_FEE_CONSTRAINT422paymentPlan.activationFeemust be a non-negative amount
50161VIN_CHECK_DIGIT_FAILED422vehicle.vinfails the ISO-3779 check digit (9th character)
50201TERM_MONTHS_CONSTRAINT422coverage.termMonthsmust be greater than 1 and at most 120
50202RETAIL_COST_CONSTRAINT422paymentPlan.retailCostmust be greater than 0 with at most 2 decimals
50203DOWN_PAYMENT_CONSTRAINT422paymentPlan.downPaymentmust be 0 or more with at most 2 decimals
50204STARTING_BALANCE_CONSTRAINT422paymentPlan.startingBalancemust be greater than 0 with at most 2 decimals
50205NUMBER_OF_INSTALLMENTS_CONSTRAINT422paymentPlan.numberOfInstallmentsmust be 1 or more
50206PROCESS_METHOD_CONSTRAINT422paymentPlan process methodmust be 1, 2 or 3
50207STARTING_BALANCE_MISMATCH422paymentPlan.startingBalancemust equal retailCost minus downPayment
50208INSTALLMENT_SPLIT_MISMATCH422paymentPlan.installmentAmountmust equal startingBalance divided by numberOfInstallments within 0.01
50210ADMINCOST_EXCEEDS_RETAIL422coverage.administratorCostmust not exceed retailCost
50213NONMTM_MONEY_REQUIRED422paymentPlanNonMTM money fields are required for NonMTM sales
50214ACTIVATION_FEE_REQUIRED422paymentPlan.activationFeeactivationFee and activationFeeProcessMethod are required for MTM sales
50215NONMTM_MONEY_FORBIDDEN422paymentPlanNonMTM money fields must be omitted for MTM sales
50216ACTIVATION_FEE_FORBIDDEN422paymentPlan.activationFeemust be omitted for NonMTM sales
51600DISCOUNT_CHART_MISSING422paymentPlan.startingBalanceno discount fee is configured for this producer, opening balance, and payment count; the sale cannot be priced. Producer configuration issue on Arch's side — contact your Arch administrator.
50301CARD_EXPIRATION_CONSTRAINT422paymentInstrument.card.expirationmust be MM/YYYY
50302HOLDER_NAME_CONSTRAINT422paymentInstrument.card.holderNamemust be 1-50 characters
50303ACCOUNT_TYPE_CONSTRAINT422paymentInstrument.bank.accountTypemust be 1 (Checking) or 2 (Savings)
50304BANK_ACCOUNT_INVALID422paymentInstrument.bank.accountNumbermust be 6-17 digits
50305BANK_ROUTING_INVALID422paymentInstrument.bank.routingNumbermust be 9 digits
50306CARD_NUMBER_INVALID422paymentInstrument.card.numbermust be a valid 15-16 digit card number
50307CARD_VAULT_FAILED422paymentInstrument.cardcard could not be vaulted with the payment processor
50308CARD_BIN_DECODE_FAILED422paymentInstrument.card.numbercard brand not recognized
50309CARD_REQUIRED422paymentInstrument.cardcard is required when paymentMethod is Card
50310BANK_REQUIRED422paymentInstrument.bankbank is required when paymentMethod is ACH
50311INSTRUMENT_FORBIDDEN_INVOICE422paymentInstrumentmust be omitted when paymentMethod is Invoice
50312INSTRUMENT_BOTH_PRESENT422paymentInstrumentprovide card or bank, not both
50313CARD_EXPIRED422paymentInstrument.card.expirationcard is expired. The expiration month is earlier than the current month (US Central); a card is accepted through the last day of its expiration month.
50314PROCESS_METHOD_CARD_ONLY422paymentPlanprocessMethod 3 (FinCo) is allowed only for Card payments
50315CARD_LUHN_FAILED422paymentInstrument.card.numbercard number failed the Luhn checksum
50316BANK_ROUTING_CHECKSUM422paymentInstrument.bank.routingNumberrouting number failed the ABA checksum
60101SALE_DATE_STALE—WarningSale date is more than 90 days old. Does not block booking.
60102ADDRESS_UNVERIFIED—WarningReserved for a future release: address verification is not yet active, so this warning is not currently emitted.
60301PROCESSOR_FALLBACK502ErrorPayment processor unavailable; the sale was not booked. Safe to retry later.
60302DOWNPAYMENT_ACTIVATION422ErrorThe card charge was declined; the sale was rejected.
60303BOOKING_FAILED_CHARGE_REVERSED500ErrorBooking failed after an approved charge; the charge was reversed automatically. Safe to resubmit.
60304BOOKING_FAILED_REVERSAL_PENDING500ErrorBooking failed after an approved charge and the reversal also failed. Do not blindly resubmit; contact Arch.
60305BOOKING_FAILED500ErrorBooking failed with no charge to reverse (nothing was charged). Safe to resubmit.
60306PROCESSOR_NOT_CONFIGURED422ErrorA due-now (FinCo) charge is owed but the producer has no payment processor configured; the sale was not booked. Permanent configuration gap — contact Arch before retrying.
60307PROCESSOR_KEY_NOT_CONFIGURED422ErrorA due-now (FinCo) charge is owed but the producer's processor has no API key assigned; the sale was not booked. Permanent configuration gap — contact Arch before retrying.
No codes match your search.

Non-Functional Requirements

Performance & timeouts

  • All calls are synchronous; the response is returned when processing completes.
  • Request bodies are capped at 1 MB; a larger request is rejected with HTTP 413 before any processing.
  • Date rules (sale date not in the future, 30-day backdate limit, 90-day stale warning) are judged on the US Central business clock, not UTC.

Pagination

Not applicable. The API has no list/collection (GET) endpoints in v1; all operations are submissions.

Idempotency & duplicate handling

  • There is no client-supplied idempotency key in v1.
  • Duplicate protection is server-side via the globally unique contractNumber (across all administrators). A repeat submission is rejected with 50008.
  • Retry guidance: on 502 or 503, no sale was booked — retry with backoff. On 500: 60303 and 60305 are safe to resubmit; with 60304, do not blindly retry — contact Arch. On 422 with 60306 or 60307, the producer's payment configuration is incomplete — contact Arch before retrying. For batches, a 200 with some rejected rows means only the rejected rows need correcting; do not resend accepted rows.

Webhooks / callbacks

None in v1. The API does not call back to partner systems; all results are returned in the synchronous response.

Security & compliance

  • Transport: HTTPS only; minimum TLS 1.2; HTTP/2 enabled.
  • Gateway: Azure API Management; an Ocp-Apim-Subscription-Key header is required on every request (sandbox and production).
  • Authentication: OAuth 2.0 client credentials; HS256-signed JWT bearer tokens; 30-minute lifetime. Client secrets stored as salted PBKDF2-SHA256 hashes.
  • Card data (PCI): card numbers are passed through to Arch's payment processor and tokenized (vaulted); ArchPay does not persist raw card numbers. CVV is not collected. Integrators must still handle card data in a PCI-compliant manner on their side.
  • Data residency: United States.

Implementation Notes & Assumptions

Key design decisions and behaviors worth knowing when building against the API.

AreaNote
Format / structure validationAll field and cross-field rules in Data Models & the Error Catalog are enforced.
Identity & duplicate checksProducer/admin/carrier existence, active, authorization; in-batch and stored duplicate detection.
Business math, date & pricing rulesMoney relationships, date rules, the stale-sale warning, card expiry (50313), and the producer discount-fee pricing check (51600).
At-sale card charge (FinCo)FinCo (method 3) amounts are charged through the payment processor configured for the producer at sale time. A producer owing a due-now charge with no processor or processor key configured is rejected before booking (60306 / 60307).
Booking / persistenceThe booking step writes the contract and returns contractId on the accepted response.

Assumptions & design decisions worth knowing

  • contractNumber is normalized (uppercased, spaces removed) before duplicate checking, and is globally unique across all administrators.
  • All independent validation problems are returned together in one response (not fail-fast within a stage).
  • Catalog message text is canonical; runtime messages may be slightly more specific (e.g. producer 3999 is not known, or a duplicate citing the existing contractId).
  • Every API response carries a requestId correlation id — including 401, 413, and 503. Gateway responses (missing/invalid subscription key 401, rate-limit 429) do not.
  • Auth failures return {"status":"rejected","requestId":"...","error":"invalid_token"} with header WWW-Authenticate: Bearer.
  • The token endpoint returns OAuth-style {"error":...} for credential/availability problems but the coded envelope for a missing form field.