Rate Lock v1 to v2 Migration Guide
This guide helps partner developers migrate a LOCK integration from the v1 result format (application/vnd.productpricing-lock-1.0.0.json or application/vnd.productpricing-lock-1.1.0.json) to the v2 result format (application/vnd.productpricing-lock-2.0.0.json). For the complete field reference, see Rate Lock (v2) and Rate Lock (v2).
What changed at a glance
| Area | v1 | v2 | Notes |
|---|---|---|---|
| Lock request values | Top level of details | requestSide object | Moved and renamed |
| Required fields | baseRate, plus two of lockDate, lockNumberOfDays, and lockExpirationDate | At least one side object | New anyOf rule |
| Dates | MM/DD/YYYY | YYYY-MM-DD | ISO 8601 |
| Rate and price fields | baseRate, basePrice, baseMarginRate | rate, priceRate, marginRate | Renamed |
| Lock period fields | lockNumberOfDays, lockExpirationDate, lastRateSetDate | numberOfDays, lockExpires, currentRateSetDate | Renamed |
| Adjustments | One adjustments[] array | Typed adjustment arrays | See Restructured adjustments |
additionalFields items | stringValue, numericValue, or dateValue | value | Single untyped value |
| New in v2 | buySide, sellSide, comparisonSide, pricingInformation | Optional |
Updating the format and entitlements
Change $.result.format from the v1 format string to the v2 format string in every transaction response that uses v2:
{
"result": {
"format": "application/vnd.productpricing-lock-1.1.0.json",
"action": "LOCK"
}
}
{
"result": {
"format": "application/vnd.productpricing-lock-2.0.0.json",
"action": "LOCK"
}
}
Then add the v2 format to the formats array for the LOCK action in your product entitlements ($.entitlements.data.transaction, response.results). During the transition you can declare both format strings to support both versions:
{
"action": "LOCK",
"formats": [
"application/vnd.productpricing-lock-1.0.0.json",
"application/vnd.productpricing-lock-1.1.0.json",
"application/vnd.productpricing-lock-2.0.0.json"
]
}
Request side and additional fields
In v1, the lock request values are sent at the top level of details. In v2, they are sent in the requestSide object, using the same field renames as the other side objects. At least one of requestSide, buySide, sellSide, or comparisonSide is required, and each side object that you send must contain at least one property.
{
"baseRate": 6.375,
"lockDate": "10/05/2026",
"lockNumberOfDays": 30,
"rateSheetId": "RS9110"
}
{
"requestSide": {
"rate": 6.375,
"lockDate": "2026-10-05",
"numberOfDays": 30,
"rateSheetId": "RS9110"
}
}
v1 additionalFields items carry the value in exactly one of stringValue, numericValue, or dateValue. v2 items carry it in a single value property, which has no defined type or format.
{
"additionalFields": [
{
"fieldName": "CX.PPE.PRICINGTIER",
"stringValue": "Gold"
}
]
}
{
"additionalFields": [
{
"fieldName": "CX.PPE.PRICINGTIER",
"value": "Gold"
}
]
}
Migrating from 1.0.0 to 1.1.0
If you only need the 1.1.0 fields, you can move from 1.0.0 to 1.1.0 without restructuring your payload. Version 1.1.0 adds investor, impoundWaived, and impoundType, and allows an empty penaltyTerm; every valid 1.0.0 payload is also valid against 1.1.0. Update $.result.format and your entitlements to the 1.1.0 format string.
Date format
Every date field in the side objects changes from MM/DD/YYYY to ISO 8601 (YYYY-MM-DD). This includes lockDate, lockExpires (formerly lockExpirationDate), currentRateSetDate (formerly lastRateSetDate), commitmentDate, and the date fields in investor and concession objects.
{
"lockDate": "01/15/2026",
"lockExpirationDate": "02/14/2026",
"lastRateSetDate": "01/15/2026"
}
{
"lockDate": "2026-01-15",
"lockExpires": "2026-02-14",
"currentRateSetDate": "2026-01-15"
}
Action required: Format all date values as YYYY-MM-DD before you submit v2 responses.
Restructured adjustments
v1 uses a single adjustments[] array on each object. Each item declares its category in adjustmentType and its sub-type in priceAdjustmentType, and carries the value in adjustment. adjustmentType, description, and priceAdjustmentType are required on every item, and each adjustments[] array must contain at least one item.
v2 replaces each adjustments[] array with separate typed arrays. Each item has priceAdjustmentTypeIndex (integer), description, and rate (decimal). None of the item fields are required, and the arrays can be empty or omitted.
{
"buySide": {
"adjustments": [
{
"adjustmentType": "Adjustment",
"priceAdjustmentType": "BaseRate",
"description": "FICO score",
"adjustment": -0.125
},
{
"adjustmentType": "LockExtensionAdjustment",
"priceAdjustmentType": "BasePrice",
"description": "15-day extension",
"adjustment": -0.25
}
]
}
}
{
"buySide": {
"baseRateAdjustments": [
{
"priceAdjustmentTypeIndex": 2,
"description": "FICO score",
"rate": -0.125
}
],
"lockExtensionAdjustments": [
{
"priceAdjustmentTypeIndex": 0,
"description": "15-day extension",
"rate": -0.25
}
]
}
}
| v2 array | Replaces v1 items with |
|---|---|
baseRateAdjustments | adjustmentType Adjustment and priceAdjustmentType BaseRate |
basePriceAdjustments | adjustmentType Adjustment and priceAdjustmentType BasePrice |
baseMarginAdjustments | adjustmentType Adjustment and priceAdjustmentType BaseMargin |
profitMarginAdjustments | adjustmentType Adjustment and priceAdjustmentType ProfitMargin (buySide only) |
lockExtensionAdjustments | adjustmentType LockExtensionAdjustment |
reLockFeeAdjustments | adjustmentType ReLockFeeAdjustment |
customPriceAdjustments | adjustmentType CustomPriceAdjustment |
Field renames
Apply these renames inside each listed object:
| v1 field | v2 field | Applies to |
|---|---|---|
lockExpirationDate | lockExpires | requestSide |
lockNumberOfDays | numberOfDays | requestSide |
startingAdjustRate | startingAdjustmentRate | requestSide |
startingAdjustPrice | startingAdjustmentPoint | requestSide |
lastRateSetDate | currentRateSetDate | requestSide |
baseRate | rate | requestSide |
basePrice | priceRate | requestSide |
baseMarginRate | marginRate | requestSide |
Fields not in v2
The following v1 fields have no field of the same name in the v2 schema. Remove them from your v2 payloads, and review any logic that depends on them.
| v1 location | v1 field | Notes |
|---|---|---|
Top level of details | extensionIndicator | Not in the v2 schema |
Top level of details | priceConcession | Not in the v2 schema |
Top level of details | borrLenderPaid | Not in the v2 schema |
Top level of details | onrpDate | Not in the v2 schema |
Top level of details | onrpTime | Not in the v2 schema |
Top level of details | onrpLock | Not in the v2 schema |
Top level of details | onrpEligible | Not in the v2 schema |
Top level of details | teaserRate | Not in the v2 schema |
Top level of details | disclosureType | Not in the v2 schema |
Top level of details | indexCurrentValuePercent | Not in the v2 schema |
Top level of details | buydownType | Not in the v2 schema |
Top level of details | pudIndicator | Not in the v2 schema |
Top level of details | notInProjectIndicator | Not in the v2 schema |
Top level of details | investor | Not in the v2 schema |
Top level of details | planCode | Not in the v2 schema |
Top level of details | gpmRate | Not in the v2 schema |
Top level of details | gpmYears | Not in the v2 schema |
Top level of details | correspondentCommitmentType | Not in the v2 schema |
Top level of details | correspondentDeliveryType | Not in the v2 schema |
Top level of details | isDeliveryType | Not in the v2 schema |
Top level of details | hedging | Not in the v2 schema |
Top level of details | penaltyTerm | Not in the v2 schema |
Top level of details | currentAcquisition | Not in the v2 schema |
Top level of details | currentConstructionRefi | Not in the v2 schema |
Top level of details | prepayPenalty | Not in the v2 schema |
Top level of details | requestImpoundWaived | Not in the v2 schema |
Top level of details | requestImpoundType | Not in the v2 schema |
Top level of details | impoundWaived | Not in the v2 schema |
Top level of details | impoundType | Not in the v2 schema |
Top level of details | lenderFeeWaiverOption | Not in the v2 schema |
Top level of details | sellerPaidMiPremium | Not in the v2 schema |
Top level of details | fhaUpfrontMiPremiumPercent | Not in the v2 schema |
Top level of details | roundToNearest50 | Not in the v2 schema |
New fields in v2
| v2 object | New field |
|---|---|
requestSide | commitmentType |
requestSide | srpPaidOut |
requestSide | onrpLockDate |
requestSide | onrpLockTime |
Complete example
The example below shows a v1 details object and the same values converted to v2 by applying the changes on this page.
{
"comments": "Lock requested at borrower request",
"programNotes": "30 year fixed conforming program",
"planCode": "99999",
"lockDate": "07/24/2020",
"lockExpirationDate": "08/30/2020",
"lastRateSetDate": "05/19/2020",
"hedging": true,
"penaltyTerm": "1 Year",
"prepayPenalty": true,
"baseRate": 5.2,
"basePrice": 4.5,
"baseMarginRate": 1.5,
"rateSheetId": "Sheet-ID-4555",
"currentAcquisition": true,
"currentConstructionRefi": false,
"gpmRate": 5.5,
"gpmYears": 10,
"requestImpoundWaived": "Waived",
"requestImpoundType": "No Impounds",
"lenderFeeWaiverOption": true,
"sellerPaidMiPremium": 1555,
"fhaUpfrontMiPremiumPercent": 2,
"roundToNearest50": true,
"adjustments": [
{
"adjustmentType": "Adjustment",
"description": "No FICO",
"priceAdjustmentType": "BasePrice",
"adjustment": 0.02
},
{
"adjustmentType": "Adjustment",
"description": "1 Year Payment Option",
"priceAdjustmentType": "BaseMargin",
"adjustment": 0.25
},
{
"adjustmentType": "Adjustment",
"description": "15 Day Lock Period",
"priceAdjustmentType": "BaseRate",
"adjustment": 0.002
},
{
"adjustmentType": "Adjustment",
"description": "Extended Payment Option",
"priceAdjustmentType": "BaseRate",
"adjustment": 0.001
},
{
"adjustmentType": "LockExtensionAdjustment",
"description": "Lock extension, 15 days",
"priceAdjustmentType": "BasePrice",
"adjustment": 0.125
},
{
"adjustmentType": "ReLockFeeAdjustment",
"description": "Relock fee",
"priceAdjustmentType": "BasePrice",
"adjustment": 0.25
},
{
"adjustmentType": "CustomPriceAdjustment",
"description": "Custom price adjustment",
"priceAdjustmentType": "BasePrice",
"adjustment": 0.05
}
],
"investor": "ABC Mortgage Investors",
"impoundWaived": "Waived",
"impoundType": "Taxes and Insurance",
"additionalFields": [
{
"fieldName": "CX.PPE.PRICINGTIER",
"stringValue": "Gold"
}
]
}
{
"requestSide": {
"comments": "Lock requested at borrower request",
"programNotes": "30 year fixed conforming program",
"lockDate": "2020-07-24",
"lockExpires": "2020-08-30",
"currentRateSetDate": "2020-05-19",
"rate": 5.2,
"priceRate": 4.5,
"marginRate": 1.5,
"rateSheetId": "Sheet-ID-4555",
"basePriceAdjustments": [
{
"priceAdjustmentTypeIndex": 0,
"description": "No FICO",
"rate": 0.02
}
],
"baseMarginAdjustments": [
{
"priceAdjustmentTypeIndex": 1,
"description": "1 Year Payment Option",
"rate": 0.25
}
],
"baseRateAdjustments": [
{
"priceAdjustmentTypeIndex": 2,
"description": "15 Day Lock Period",
"rate": 0.002
},
{
"priceAdjustmentTypeIndex": 2,
"description": "Extended Payment Option",
"rate": 0.001
}
],
"lockExtensionAdjustments": [
{
"priceAdjustmentTypeIndex": 0,
"description": "Lock extension, 15 days",
"rate": 0.125
}
],
"reLockFeeAdjustments": [
{
"priceAdjustmentTypeIndex": 0,
"description": "Relock fee",
"rate": 0.25
}
],
"customPriceAdjustments": [
{
"priceAdjustmentTypeIndex": 0,
"description": "Custom price adjustment",
"rate": 0.05
}
]
},
"additionalFields": [
{
"fieldName": "CX.PPE.PRICINGTIER",
"value": "Gold"
}
]
}
Migration checklist
- Update
$.result.formattoapplication/vnd.productpricing-lock-2.0.0.jsonin all transaction responses that use v2. - Add
application/vnd.productpricing-lock-2.0.0.jsonto theformatsregistered forLOCKin your product entitlements. - Move the top-level lock request fields into
requestSide. - Convert
additionalFieldsitems tofieldNameandvalue. - Convert all dates from
MM/DD/YYYYtoYYYY-MM-DD. - Apply the field renames in each object.
- Split each
adjustments[]array into the typed adjustment arrays, usingpriceAdjustmentTypeIndex,description, andrate. - Remove the fields that are not in v2.
- Validate your v2 payloads against the JSON schema before deploying to production.
Support
If you have questions about this migration or encounter v2 validation issues, post them on our Discussion board or contact the EPC team at [email protected]. We recommend validating your v2 payloads against the JSON schema, and testing them in your EPC sandbox, before deploying to production.
Updated 4 days ago
