Opportunities webhook

Opportunities webhook

Target audience: Developers who are integrating with the Gensen salary sacrifice system and need to receive opportunities (including employee, vehicle and quote information) through a webhook API.

Event triggers

The opportunities webhook is triggered when an employee applies for a car within the salary sacrifice platform.

Payload

The webhook will send a POST request to an agreed endpoint URL with a JSON body described by OpportunityRequest, which is a container type for SalsacQuote.

Security

The webhook can be secured using an agreed shared secret (token) that will be sent in the authorization header of the request:

authorization: Bearer <shared secret>

Retry policy

At present there are no retries. If the webhook fails, we store the data within our system and can resend it manually.

We hope to implement retries in the future.

Update policy

The webhook will be updated to preserve forward compatibility whenever possible. We may add new fields to the request object, but any new response fields will be optional.

We may be required to make breaking changes in response to UK government policy changes and we will endeavour to document changes as soon as possible.

Sample request/response

Request

POST /opportunity/create HTTP/1.1
host: example.com
content-type: application/json
authorization: Bearer <shared secret>

{
    "data": {
        "client_vehicle_id": "abc123",
        "rate_source": "ratebook",
        "cap_id": 92358,
        "model_year": "2022.25",
        "cap_option_ids": [
            "156105",
            "147970"
        ],
        "cap_vehicle_type": "C",
        "make": "Ford",
        "model": "Cortina",
        "derivative": "1.5L LX",
        "p11d_value": 76483.01,
        "co2_emissions": 0,
        "client_rate_id": "xyz123",
        "term_months": 36,
        "mileage_yearly": 10000,
        "initial_payments": 1,
        "payment_profile": "S",
        "rental": 234.56,
        "maintenance": 75.31,
        "effective_rental": 735.12,
        "effective_maintenance": 205.12,
        "one_up_front_effective_rental": 735.12,
        "one_up_front_effective_maintenance": 205.12,
        "contingency_fee": 48.12,
        "insurance_premium": 180.21,
        "salary_sacrifice_gross": 23134,
        "salary_sacrifice_net": 18765,
        "nic_saving_shared_with_employee": 1234,
        "salary_sacrifice_gross_pre_nic_sharing": 23134,
        "employer_nic_savings_shared": 0,
        "employer_nic_savings_shared_fraction": 0,
        "employee": [
            {
                "year": "2021/22",
                "income_tax_saving": -123.45,
                "salary_sacrifice_net": 123.45,
                "salary_sacrifice_gross": 123.45,
                "bik_tax": 123.45,
                "nic_saving": -123.45,
                "salary_sacrifice_gross_pre_nic_sharing": 123.45,
                "nic_saving_shared_with_employee": 0,
                "tax_saving": -123.45,
                "hscl_saving": 0
            },
            {
                "year": "2022/23",
                "income_tax_saving": -123.45,
                "salary_sacrifice_net": 123.45,
                "salary_sacrifice_gross": 123.45,
                "bik_tax": 123.45,
                "nic_saving": -123.45,
                "salary_sacrifice_gross_pre_nic_sharing": 123.45,
                "nic_saving_shared_with_employee": 0,
                "tax_saving": -123.45,
                "hscl_saving": 0
            },
            {
                "year": "2023/24",
                "income_tax_saving": -123.45,
                "salary_sacrifice_net": 123.45,
                "salary_sacrifice_gross": 123.45,
                "bik_tax": 123.45,
                "nic_saving": -123.45,
                "salary_sacrifice_gross_pre_nic_sharing": 123.45,
                "nic_saving_shared_with_employee": 0,
                "tax_saving": -123.45,
                "hscl_saving": 0
            }
        ],
        "employer": [
            {
                "year": "2021/22",
                "nic_saving": 123.45,
                "class_1_nic_saving": 123.45,
                "class_1_nic_saving_original": 123.45,
                "class_1a_nic": 123.45,
                "nic_savings_shared": 0,
                "hscl_saving": 0,
                "hscl": 0
            },
            {
                "year": "2022/23",
                "nic_saving": 123.45,
                "class_1_nic_saving": 123.45,
                "class_1_nic_saving_original": 123.45,
                "class_1a_nic": 123.45,
                "nic_savings_shared": 0,
                "hscl_saving": 0,
                "hscl": 0
            },
            {
                "year": "2023/24",
                "nic_saving": 123.45,
                "class_1_nic_saving": 123.45,
                "class_1_nic_saving_original": 123.45,
                "class_1a_nic": 123.45,
                "nic_savings_shared": 0,
                "hscl_saving": 0,
                "hscl": 0
            }
        ],
        "pch": 518.88,
        "vat_partial_exemption_fraction": 0.95,
        "early_termination_contingency_amount": null,
        "early_termination_contingency_fraction": 0.04,
        "early_termination_insurance_premium": 0,
        "early_termination_insurance_fraction": 0.087654,
        "early_termination_protection_monthly": 0,
        "effective_early_termination_protection_monthly": 0,
        "customer_id": 91533,
        "user_id": 75643,
        "name": "Lavern Bauch",
        "given_name": "Lavern",
        "family_name": "Bauch",
        "contact_number": null,
        "email": null,
        "marketing_email_consent": null,
        "marketing_sms_consent": null,
        "residence": "Scotland",
        "income_tax_rate_first_year": 0.21,
        "postcode": "AB12 1AB",
        "address": null,
        "motor_insurance_type": "Default",
        "motor_insurance_provider": "LloydLatchford",
        "insurer_quote_id": "XYZ12345",
        "insurance_quote_datetime": "2021-05-18T09:12:34.56Z",
        "driver_1_dob": "1980-06-05",
        "driver_2_dob": "1981-03-01",
        "driver_3_dob": null,
        "driver_1_name": "Sade",
        "driver_2_name": "El Greco",
        "driver_3_name": null,
        "personal_contract_hire_yn": "N",
        "maintenance_yn": "Y",
        "gensen_quote_id": "00012345"
    }
}

Success response

{
    "data": {
        "opportunity_id": "12345"
    }
}

Error response

{
    "errors": [
        {
            "code": "12345",
            "message": "An message we can log for later debugging"
        }
    ]
}

An appropriate HTTP status error code (4xx or 5xx) is expected for an error response.

Testing

At the moment we do not have a specific test environment for the webhook, though we suggest adapting the sample request above to test your implementation.


Schema

Scalar Types

NameDefinitionDescription
Yes"Y"
No"N"
TerminalPause"P"
SpreadRental"S"
Residence"UK" | "Scotland" | "Wales"
Car"C"
Lcv"L"
Decimalnumber
Decimal2DpsDecimal
Decimal1DpDecimal
Integernumber
ExVatAmountnumber
VatIncAmountnumber
Amountnumber
RateSource"ratebook" | "lex"
MotorInsuranceType"Default" | "EmployerProvided"
Iso8601Date'${number}-${number}-${number}'
Iso8601DateTime'${Iso8601Date}${"T" | " "}${number}:${number}:${number}${string}'

Object Types

SalsacQuote

The quote sent to a CRM as an opportunity or as a final quote recalculation.

FieldTypeDescription
addressPostalAddress | nullThe address where the vehicle will be parked overnight. Not provided for employer-supplied or private insurance.
cap_idnumber | nullThe cap ID of the car, where available.
cap_option_idsstring[] | nullnull indicates no selection was made, whereas an empty array indicates no options were selected. CAP IDs as provided by CAP’s SOAP option bundle endpoint
See https://soap.cap.co.uk/nvd/capnvd.asmx?op=GetCapOptionsBundle IDs may include options that have inclusive pricing from “IN” and “IO” rules and should be removed from P11D and rental pricing. Where more than one item in an IO rule is selected, the most expensive is offered for free. At time of writing, users are not blocked from enquiries on invalid option combinations and merely indicate a preference.
cap_vehicle_type"C"For salsac, this is always “C” for car.
client_rate_idstring | nullRate ID as provided on import, where available. Treat this as the canonical, source-specific rate identifier. For Lex rates, this will indicate the product code only, there is no unique rate identifier.
client_vehicle_idstring | nullVehicle ID as provided on import, where available. Treat this as the canonical, source-specific vehicle identifier. For Lex vehicles, this carries the raw identifier returned by Lex.
co2_emissionsnumber
contact_numberstring | nullEmployee’s phone number
contingency_feenumberAny contingency fee added to the quote, ex VAT
customer_idstring | number | nullIdentifier for the employer as provided, where available. A string will be returned (unless previously agreed to send as an integer)
derivativestring
driver_1_dob'${number}-${number}-${number}'Driver 1 date of birth
Example: "1983-01-29"
driver_1_namestringDriver 1 name (may be different from employee name in some cases)
Example: "Jane Smith"
driver_2_dob'${number}-${number}-${number}' | nullDriver 2 date of birth
Example: "1983-01-29"
driver_2_namestring | nullDriver 2 name
Example: "John Smith"
driver_3_dob'${number}-${number}-${number}' | nullDriver 3 date of birth
Example: "1983-01-29"
driver_3_namestring | nullDriver 3 name
Example: "Jake Smith"
early_termination_contingency_amountnumber | nullAmount of contingency fee, ex VAT
early_termination_contingency_fractionnumber | nullContingency fee as a fraction of the ex VAT total rental
early_termination_insurance_fractionnumber | nullThe amount of early termination insurance that is applied, as a fraction of the ex VAT rental + maintenance.
early_termination_insurance_premiumnumberMonthly insurance premium for early termination
early_termination_protection_monthlynumber | nullThe amount of early termination protection that is applied as part of the overall rental cost (ex VAT). Will report as zero for recalculations where the original rental should include the ETP amount.
effective_early_termination_protection_monthlynumber | nullThe amount of early termination protection that is applied as part of the overall rental cost. Takes account of any VAT recovery or blockage. Will report as zero for recalculations where the original rental should include the ETP amount.
effective_maintenancenumberRepresents a periodic business lease maintenance, taking account of VAT recovery and the Lease Rental Restriction. Any upfront maintenance will be applied, rather than converted to a 1-0-x payment profile.
effective_rentalnumberRepresents a periodic business lease rental, taking account of VAT recovery and the Lease Rental Restriction. Early termination protection is not included, except when included in the original rental. Any upfront rental will be applied, rather than converted to a 1-0-x payment profile.
emailstring | nullEmployee’s email address
employeeSalsacQuoteEmployee[]Breakdown of employee costs and savings by year
employerSalsacQuoteEmployer[]Breakdown of employer costs and savings by year
employer_nic_savings_sharednumberThe average monthly class 1 NIC savings shared by employer with employee over the full term
employer_nic_savings_shared_fractionnumberThe fraction of the employer NIC savings shared with the employee. 1 represents 100% of the employer NIC savings shared with the employee, 0 represents 0% of the employer NIC
family_namestring | nullEmployee’s family name
gensen_quote_idstringIdentifier for the quote in the Gensen system.
given_namestring | nullEmployee’s given name
income_tax_rate_first_yearnumberEmployee’s tax rate for the first year of the lease.
initial_payments1All salsac quotes are based on 1 in advance, so this will always be 1.
insurance_premiumnumberAnnual motor insurance premium quoted
insurance_quote_datetime'${number}-${number}-${number} ${number}:${number}:${number}${string}' | '${number}-${number}-${number}T${number}:${number}:${number}${string}'Date stamp for motor insurance quote.
insurer_quote_idstringMotor insurer’s quote ID.
maintenancenumberPeriodic ex VAT maintenance amount Converted to 1-0-x if necessary.
maintenance_yn"Y"
Deprecated: Will be removed in future versions, don’t depend on this.
makestring
marketing_email_consentboolean | nullConfirmation that the employee has consented to email marketing.
marketing_sms_consentboolean | nullConfirmation that the employee has consented to SMS marketing.
mileage_yearlynumberLease mileage allowance per year
modelstring
model_yearstringMany cap ID or cap codes represent a range of cars over several years, so model year is required to disambiguate.
Example: "2024.25"
motor_insurance_providerstring | nullMotor insurance provider name (if applicable).
motor_insurance_typeMotorInsuranceType | nullMotor insurance type (if included in the quote).
namestringEmployee’s full name
nic_saving_shared_with_employeenumberAverage monthly employer class 1 NIC saving shared with employee.
one_up_front_effective_maintenancenumberThe effective_maintenance represents a periodic business lease maintenance and will take account of VAT recovery and the Lease Rental Restriction. Payments converted to 1-0-x if necessary.
one_up_front_effective_rentalnumberRepresents a periodic business lease rental so will take account of VAT recovery and the Lease Rental Restriction. Early termination protection is not included, except when included in the original rental. Payments converted to 1-0-x if necessary.
p11d_valuenumber
payment_profile"S"All salsac quotes are based on spread rental, so this will always be “S”.
pchnumberIncludes rental, maintenance, insurance, but not contingency fee.
personal_contract_hire_yn"N"
Deprecated: Will be removed in future versions, don’t depend on this.
postcodestring | nullPostcode where the vehicle will be parked overnight. Not provided for employer-supplied or private insurance.
rate_source?RateSourceIdentifies the source of the underlying vehicle and rate data. Prefer ratebook for partner-provided ratebooks. Use lex for quotes sourced from Lex’s used car API.
rentalnumberPeriodic ex VAT rental amount. Doesn’t include any applicable early termination protection. Converted to 1-0-x if necessary.
request_typeRequestType | undefinedIndicates whether this was requested as an enquiry or an order.
residenceResidenceEmployee’s residence for tax purposes.
salary_sacrifice_grossnumberAverage monthly gross cost over the full term
salary_sacrifice_gross_pre_nic_sharingnumberIf NIC is shared, represents the gross salary sacrifice amount before NIC is deducted
salary_sacrifice_netnumberThe average monthly net cost over the full term
term_monthsnumberLease term in months
user_idstring | number | nullIdentifier for the employee within Gensen. A string will be returned (unless previously agreed to send as an integer)
vat_partial_exemption_fractionnumber | null1 represents 100% VAT recovery by the employer, 0 represents 0% VAT recovery.

SalsacQuoteEmployee

Represents employee costs over a financial year.

FieldTypeDescription
bik_taxnumber
hscl_saving0
Deprecated: Will be removed in a future version.
income_tax_savingnumber
nic_savingnumber
nic_saving_shared_with_employeenumberEmployer class 1 NIC saving shared with employee.
salary_sacrifice_grossnumber
salary_sacrifice_gross_pre_nic_sharingnumber
salary_sacrifice_netnumber
tax_savingnumber
yearstring

SalsacQuoteEmployer

FieldTypeDescription
class_1_nic_savingnumber
class_1_nic_saving_originalnumberThis is the employer’s NIC saving prior to sharing with the employee.
class_1a_nicnumber
hscl0
Deprecated: Will be removed in a future version.
hscl_saving0
Deprecated: Will be removed in a future version.
nic_savingnumber
nic_savings_sharednumber
yearstring

SalsacQuoteRequest

FieldTypeDescription
external_refstring
initial_paymentsnumberIf terminal pause (TP), the payments will be converted into spread rental, and if more than 1 in advance, will be converted to 1-0-x. Early termination protection (ETP) is only available on 1 in advance, spread rental, and an error will be returned for invalid payment profiles.
maintenancenumber
mileage_yearlynumber
p11d_valuenumber
payment_profile"S" | "P"
previous_gensen_quote_idstring
rentalnumber
term_monthsnumberTerm must match original quote on recalculation, because the motor insurance quote is only valid for the original term.

OpportunityRequest

FieldTypeDescription
dataSalsacQuote

OpportunityResponse

The response expected from the 3rd-party CRM after creating an opportunity.

FieldTypeDescription
data?{ opportunity_id: string | number }
errors?readonly { code?: string; message: string }[]Only required if there is an issue creating the opportunity. Note that this is a machine-to-machine API and so any error messages can only be logged for later debugging.
status?number
Deprecated: Legacy field, 0 indicates success, anything else indicates failure. Still used by eFleet (FASS).

Scalar Types

interface PostalAddress {
    line1: string;
    line2?: string;
    line3?: string;
    line4?: string;
    line5?: string;
    postcode: string;
}

Object Types

  • 2024-08-14

    • SalsacQuote:
      • Added field address and related type PostalAddress.
      • Clarified that postcode may be null for employer-supplied or private insurance.
  • 2023-07-26

    • SalsacQuote:
      • Added fields effective_early_termination_protection_monthly, one_up_front_effective_rental, one_up_front_effective_maintenance
    • SalsacQuoteRequest:
      • Clarified that some payment profiles may be invalid with ETP.
  • 2023-07-07

    • SalsacQuote:
      • Added fields salary_sacrifice_gross_pre_nic_sharing, employer_nic_savings_shared, employer_nic_savings_shared_fraction, early_termination_insurance_premium, early_termination_insurance_fraction, early_termination_protection_monthly
    • SalsacQuoteEmployee:
      • Added fields salary_sacrifice_gross_pre_nic_sharing, nic_saving_shared_with_employee
    • SalsacQuoteEmployer:
      • Added field nic_savings_shared, class_1_nic_saving_original