Skip to main content

Configure External Pricing for Proposals

Connect Smarter Launch to a company-managed pricing service and return proposal pricing through a secure external endpoint.

🚧 In Development

External Pricing is currently in development and is not yet generally available.

External Pricing lets Smarter Launch retrieve proposal prices from a pricing service that your company controls. It is useful when pricing depends on proprietary rules, customer or property data, internal rate tables, territory-specific logic, or another system that should remain the source of truth.

Once configured, Smarter Launch sends the relevant proposal data to your endpoint from the Smarter Launch API—not directly from the user's browser. Your service returns the initial and recurring price, and Smarter Launch retains that price on the proposal.

Before you begin

External Pricing is an optional, admin-managed integration and must be enabled for your company by a Smarter Launch administrator. After it is enabled, users who have permission to update company integrations can configure and test endpoints.

You will need:

  • An HTTPS endpoint that is reachable over the public internet

  • Any authentication headers required by your service

  • A response that follows the format described below

  • Permission to update company integrations and service plans in Smarter Launch

External pricing requests may contain customer, address, custom-field, and proposal pricing data. Only connect services that your company trusts and is authorized to use for this data.

Why use External Pricing?

External Pricing can help when a flat rate, per-unit rate, or Smarter Launch dynamic range does not fully represent your pricing model. Common examples include:

  • Pricing from an internal CPQ, ERP, or rate-management system

  • Rates that vary by territory, customer type, property attributes, or service selections

  • Proprietary formulas that should not be recreated in Smarter Launch

  • Centralized pricing shared across Smarter Launch and other company systems

  • Pricing models that change frequently and should be maintained in one place

Add an external pricing endpoint

  1. Open Company Settings and select Integrations.

  2. Open External Pricing.

  3. Confirm that the integration is enabled. If it is unavailable or cannot be enabled, contact Smarter Launch Support.

  4. Select Add Endpoint.

  5. Configure the endpoint:

    • Name: A recognizable name for users selecting the endpoint in a service plan.

    • Method: GET, POST, PUT, or PATCH. POST is recommended for most pricing services.

    • HTTPS URL: The complete public URL that will receive pricing requests.

    • Timeout: The number of seconds Smarter Launch should wait, from 1 to 30 seconds. The default is 15 seconds.

    • Headers: Add authentication or other headers required by your service.

    • Active: Only active endpoints can be assigned to pricing groups or tested.

    • Default: The default endpoint is preselected when a user creates a new External pricing group.

  6. Select Save Changes.

The first endpoint you add is automatically set as the default. You can use the star in an endpoint's header to make a different active endpoint the default.

Protect sensitive headers

Mark credentials such as Authorization, API keys, and tokens as private. Private values are encrypted and concealed after they are saved. A concealed value can remain unchanged when editing the endpoint; enter a new value only when you need to rotate the credential.

Smarter Launch does not allow credentials embedded in the endpoint URL. It also blocks connection-specific headers such as Host and Content-Length.

Test an endpoint

Use the play icon beside an active endpoint to send a test request.

  1. Select the endpoint's Test action.

  2. Find and select a recent proposal.

  3. Select Send Test.

  4. Review the request and response payloads shown after the test.

The test always calls the endpoint you selected. The proposal does not need to have a pricing group assigned to that endpoint. If it contains External pricing groups assigned to other endpoints, those pricing options are marked as external pricing targets for the test. If it has no External pricing groups, the request is still sent with the service-plan hierarchy and no pricing options marked as external pricing targets, so you can verify the URL, method, headers, connectivity, and basic response format.

Test responses are never saved as proposal prices.

Configure a service plan to use External Pricing

After at least one active endpoint is available:

  1. Open the service plan you want to configure.

  2. Add or edit a pricing group.

  3. Set Pricing Type to External.

  4. Enter the External Pricing Prompt. This is the question or label shown while building the proposal and is also sent to your pricing service.

  5. Select the Pricing Endpoint.

  6. Select a Prompt Response Type:

    • Number: For values such as square footage, linear feet, quantity, or another numeric input.

    • Yes / No: For a Boolean selection. Both true and false are valid values.

  7. Set the default prompt value, if needed.

  8. Save the pricing group and service plan.

A new External pricing group initially uses the default endpoint. You can assign different pricing groups to different endpoints.

Request sent to your endpoint

Smarter Launch sends a JSON request body. A live request resembles the following:

{
  "request_id": "1f04f30a-f3d1-4f45-83e4-16c6221ea699",
  "proposal": {
    "uuid": "89e12771-d1f8-4823-86d8-7953d5bdf884",
    "version_uuid": "90311ace-88bb-49c0-9454-450add1a47fe",
    "title": "Commercial Pest Control",
    "status": "PROPOSAL_DRAFT",
    "proposal_type": "standard",
    "template": {
      "uuid": "ff1430aa-d192-45e8-84fc-e23df947d513",
      "title": "Commercial Proposal",
      "display_name": "Commercial Proposal",
      "proposal_type": "standard"
    },
    "assigned_user": {
      "uuid": "0626258b-da96-49ba-8134-b5d8ba18ce6f",
      "display_name": "Alex Smith",
      "email": "[email protected]",
      "phone": "6025550123",
      "position": "Account Executive"
    }
  },
  "company": {
    "uuid": "1997fbd7-34e8-4c1f-8acf-64b4ab9c92e3",
    "name": "Acme Pest Control",
    "phone": "6025550190",
    "email": "[email protected]",
    "website_url": "https://example.com",
    "license_number": "AZ-12345",
    "address": {
      "address1": "500 Central Avenue",
      "city": "Phoenix",
      "state": "AZ",
      "postal_code": "85004",
      "country": "US"
    },
    "custom_field_values": {}
  },
  "company_location": {
    "uuid": "cc91bdf2-37d1-43ff-a9c8-d8bc5dd78cd9",
    "name": "Acme Pest Control \u2013 Phoenix",
    "description": "Phoenix service location",
    "time_zone": "America/Phoenix",
    "contact": {
      "phone": "6025550199",
      "email": "[email protected]"
    },
    "address": {
      "address1": "1000 West Washington Street",
      "city": "Phoenix",
      "state": "AZ",
      "postal_code": "85007",
      "country": "US"
    },
    "custom_settings": []
  },
  "customer": {
    "uuid": "d784854b-e61e-48bd-8c84-6471efe192d3",
    "account_name": "Acme Property Management",
    "custom_field_values": {},
    "selected_contact": {
      "uuid": "022e3471-74a7-4d54-87fc-e8d0120fb658",
      "first_name": "Jamie",
      "last_name": "Rivera",
      "email": "[email protected]",
      "phone": "6025550100",
      "is_primary": true
    },
    "selected_service_address": {
      "uuid": "dd60a5b2-9701-4ca8-9361-78335068ead7",
      "address1": "123 Main Street",
      "address2": "Suite 200",
      "city": "Phoenix",
      "state": "AZ",
      "postal_code": "85001",
      "country": "US",
      "county": "Maricopa",
      "latitude": 33.4484,
      "longitude": -112.074,
      "custom_field_values": {}
    }
  },
  "service_plans": [
    {
      "uuid": "45094217-032b-4a9a-840f-b3407f50c26a",
      "name": "Commercial Pest Control",
      "display_name": "Commercial Pest Control",
      "description": "Recurring commercial pest service",
      "proposal_type": "standard",
      "contract_term": null,
      "categories": [],
      "custom_fields": [
        {
          "uuid": "d5ca7787-0aee-4168-ac31-00f2f7e6d09e",
          "name": "Property Type",
          "input_type": "TEXT",
          "is_hidden_from_customer": false,
          "value": "Commercial"
        }
      ],
      "pricing_options": [
        {
          "uuid": "db415395-f86e-474f-900c-b1a33d327843",
          "name": "Property Size Pricing",
          "description": null,
          "pricing_type": "EXTERNAL_PRICE",
          "prompt": "Approximate square footage",
          "input_type": "NUMBER",
          "entered_value": 2500,
          "included": true,
          "selected": true,
          "customer_can_toggle": true,
          "locked": false,
          "recommended": true,
          "is_additional": false,
          "is_external_pricing_target": true,
          "external_pricing_endpoint_uuid": "a704471e-c912-4f9c-ad47-bf23865bd859",
          "configured_price": {
            "initial_price": null,
            "recurring_price": null
          },
          "calculated_price": null,
          "external_price": null,
          "quantity": 1,
          "is_quantity_enabled": true,
          "apply_taxes": true,
          "tax_type": "SERVICES",
          "billing_schedule": null,
          "service_schedule": null,
          "custom_values": []
        }
      ]
    }
  ],
  "general_adjustments": []
}

Test requests include an additional field:

{
  "is_test": true
}

The service_plans array mirrors the proposal hierarchy. Each service plan contains its descriptive details, named custom fields and values, and a pricing_options array. Proposal-level additional items appear under a synthetic service plan named Additional Items.

Each pricing option includes its name, prompt, entered value, pricing type, selected/locked/recommended state, schedules, configured pricing, calculated pricing when available, and the retained external price when one exists. is_external_pricing_target identifies the options for which the receiving endpoint must return prices. Other pricing options are included as proposal context and do not require response items.

customer.selected_service_address is the property address selected on the proposal. It is separate from the selling company's address. company_location identifies the branch associated with the proposal. Its name, description, contact, and address are already resolved using the same company-location override rules used when presenting the proposal: location override values are provided when enabled, otherwise the company values are provided.

All request field names use snake_case, including fields nested inside settings and custom values. customer.selected_contact and customer.selected_service_address are null when the proposal does not have those selections.

The body delivered to your endpoint is the expanded proposal hierarchy shown above. The smaller pricing_context used between the proposal editor and the Smarter Launch API is an internal transport format; it is resolved server-side and is never forwarded to your pricing service.

Expected response

Your endpoint must return a successful HTTP response with a JSON object containing an items array:

{
  "items": [
    {
      "service_plan_uuid": "45094217-032b-4a9a-840f-b3407f50c26a",
      "pricing_group_uuid": "db415395-f86e-474f-900c-b1a33d327843",
      "initial_price": 149.0,
      "recurring_price": 49.0,
      "tax_rate": 8.25,
      "currency": "USD",
      "external_reference": "quote-10482",
      "metadata": {
        "rate_version": "2026.07"
      }
    }
  ]
}

Return this as the raw response body. Do not wrap it in the Smarter Launch API status, code, msg, or data response structure. Item order does not matter.

Each requested item must have exactly one matching response item.

Field

Required

Description

items

Yes

An array of calculated pricing results. It may be empty when a test request contains no pricing options marked as external pricing targets.

service_plan_uuid

Yes

Must match the parent service plan UUID for a pricing option marked is_external_pricing_target: true.

pricing_group_uuid

Yes

Must match the UUID of a pricing option marked is_external_pricing_target: true. Do not return duplicates for the same pricing option.

initial_price

Yes

A number greater than or equal to zero.

recurring_price

Yes

A number greater than or equal to zero, or null when the item has no recurring charge.

tax_rate

No

The percentage tax rate to apply to this pricing option, such as 8.25. Use null or omit the field to use the proposal's normal company tax or ZIP Tax calculation. The returned rate is only applied when the pricing option is configured as taxable.

currency

No

Defaults to USD when omitted. Only USD is currently supported.

external_reference

No

Your quote, calculation, or transaction identifier.

metadata

No

An object containing additional information your service wants retained with the pricing result.

For a one-time price, return null for recurring_price; do not omit the field.

When tax_rate is returned, Smarter Launch applies that rate only to the matching External pricing option. It does not replace the company's tax settings for other pricing. If the field is omitted or null, taxable External pricing continues to use ZIP Tax when enabled, or the matching company tax settings otherwise. If the pricing option is not configured as taxable, the returned rate is retained but not applied.

How Smarter Launch processes the response

Smarter Launch does not pass your endpoint response directly through to the proposal editor. It matches each result by service plan and pricing group UUID, validates the amounts, normalizes the supported fields, and retains the verified price on the proposal. Smarter Launch then adds retrieval status, stale-price information, validation errors, and recalculated proposal totals to its own response to the editor.

Only initial_price, recurring_price, tax_rate, currency, external_reference, and object-valued metadata are retained from each result. Additional response fields are ignored.

When pricing is requested

While a proposal is being edited, Smarter Launch automatically refreshes selected External pricing after a relevant pricing input changes; saving the proposal is not required to request the new price. Relevant inputs include the selected customer contact and service address, company location, service plans, pricing prompt values, service-plan custom fields, additional pricing, pricing overrides, selected or locked pricing groups, general adjustments, and endpoint assignments.

Users can also select Refresh Pricing in the proposal's service-plan step to request a new calculation immediately.

Smarter Launch groups requested items by endpoint, so a proposal can use multiple pricing services. Calls are made from the Smarter Launch API, not the browser.

Retained and stale pricing

Successful initial and recurring amounts, along with an optional external tax rate, are stored with the proposal. Smarter Launch reuses the retained value until a relevant input changes or a user explicitly refreshes pricing.

If a later refresh fails, the previous price is retained and marked as stale instead of being removed. The proposal displays a warning and continues using the retained price until a refresh succeeds. This prevents a temporary endpoint outage from unexpectedly clearing proposal totals.

Endpoint requirements and limits

  • The URL must use HTTPS and resolve only to public IP addresses.

  • Localhost, private-network destinations, URL-embedded credentials, and redirects are not allowed.

  • The endpoint must respond within its configured timeout of 1–30 seconds.

  • The response body cannot exceed 1 MB.

  • The response must be valid JSON and contain an items array.

  • Only USD pricing is currently supported.

  • Endpoint calls are made server-side by Smarter Launch.

Troubleshooting

The endpoint test fails before reaching my service

Confirm that the URL uses HTTPS, the hostname resolves publicly, the endpoint is active, and the timeout is long enough. Private or local IP addresses are intentionally blocked.

The endpoint returns an error status

Smarter Launch treats non-successful HTTP responses as failures. Check your service logs, authentication headers, request method, and response time.

No price was returned for a pricing group

Confirm that your response includes one item whose pricing_group_uuid and service_plan_uuid match each request pricing option marked is_external_pricing_target: true.

The recurring price validation fails

Always include recurring_price. Use a nonnegative number for recurring service or null for one-time-only pricing.

Pricing is marked stale

The most recent refresh did not succeed or the proposal inputs changed after the retained price was calculated. Correct the endpoint or response issue, then select Refresh Pricing again.

An endpoint cannot be deleted

Endpoints assigned to one or more External pricing groups cannot be deleted. Reassign those pricing groups to another active endpoint before deleting it.

The External pricing type is unavailable

Confirm that the External Pricing integration is enabled for your company. Because activation is admin managed, Smarter Launch Support may need to enable it first. If the External pricing type appears but cannot be configured, confirm that at least one active endpoint is available.

Did this answer your question?