Add services to an offer
const url = 'https://apisandbox.puurk.com/offers/example/services';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"services":[{"service_id":"svc_7Hk2LqRm","quantity":1,"merge_contract_id":"example"}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://apisandbox.puurk.com/offers/example/services \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "services": [ { "service_id": "svc_7Hk2LqRm", "quantity": 1, "merge_contract_id": "example" } ] }'Add one or more services to an existing offer
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”ID of the offer
Request Bodyrequired
Section titled “Request Bodyrequired”Services to add
Body for POST /offers/{offerId}/services. Note the field names differ from the OfferService response shape: only service_id, quantity and merge_contract_id are writable here. The service name and line amount always come from the organization’s service catalog.
Services can also be supplied inline on POST /offers, in the services array of the offer body — that path creates the offer and its lines in one call, and is the one to reach for when you are creating the offer anyway. Use this endpoint to add lines to an offer that already exists.
object
Between 1 and 500 service lines.
object
Must match a service belonging to the offer’s organization, otherwise the request fails with service_not_found.
Example
svc_7Hk2LqRmGreater than 0. Fractional quantities are allowed.
Example
1Optional merge contract to attach the line to.
Responses
Section titled “Responses”Services added; returns the re-priced offer
object
Unique identifier for the offer
client — a plan for a specific client; requires lead_id. template — a shareable, client-less plan (the provider app calls these “Templates”); lead_id, lead_name and uid are always null on one.
Null on offers created before the type was recorded, until the backfill stamps them. Newly created offers are never null — an offer created with a lead_id and no type is stored as client.
The client this plan is for. Required when type is client or omitted. On a template it is always null in the response: one sent in the request is ignored rather than rejected.
Always null on a template offer.
Always null on a template offer.
Deprecated
Deprecated
object
Offer these terms belong to
User the terms were generated for
Down payment in cents
Amount financed in cents
Provider’s share of the premium as a fraction between 0 and 1
Plan length in months
Premium charged per month in cents
Provider share of the monthly premium in cents
Puurk share of the monthly premium in cents
Principal per month in cents
Fees included in each monthly payment in cents
Payout fees per month in cents
Provider fees per month in cents
Monthly payment in cents
Monthly opportunity for the provider in cents
Total paid over the plan in cents
Total premium over the plan in cents
Provider share of the total premium in cents
Puurk share of the total premium in cents
Total principal (down payment plus financed amount) in cents
Total fees over the plan in cents
Total payout fees over the plan in cents
Total provider fees over the plan in cents
Total opportunity for the provider in cents
object
User id of the salesperson
object
Example
{ "type": "template", "lead_id": "fLp5zssaLLRcKDbh0DpP", "lead_name": "John Doe", "uid": "l8zcL5Va8ei6QQlmhe8n", "location_id": "g9WWX7DJ0ev6WZ2rOhdQ", "merge_contract_id": null, "oid": "iQyjWJf77rrVUx8HJshp", "organization_name": "Acme Medical", "provider_id": null, "provider_name": null, "providers": [ "4NoHg9a7Yf0QODl1IMcE", "WKVlP1g5arHJdDa2yBir" ], "title": "Plan 1234", "payment_option": "finance", "postpone_reason": "expensive", "status": "pending"}Validation failed. error is invalid_params and message names the offending field, e.g. Invalid value: services[0].quantity must be a number greater than 0.
The standard error body. error is a stable, machine-readable code — branch on it rather than on message, which is for humans and may change.
object
Machine-readable error code.
Human-readable detail.
Example
{ "error": "merchant_account_missing", "message": "The organization has no merchant account. Complete Stripe Connect onboarding for this organization before generating pricing."}Unauthorized
not_found when the offer does not exist, or service_not_found when a service_id matches no service for the offer’s organization.
The standard error body. error is a stable, machine-readable code — branch on it rather than on message, which is for humans and may change.
object
Machine-readable error code.
Human-readable detail.
Example
{ "error": "merchant_account_missing", "message": "The organization has no merchant account. Complete Stripe Connect onboarding for this organization before generating pricing."}The organization is not ready to be priced: merchant_account_missing when it has no merchant account, merchant_account_inactive when its merchant account is not active, or card_method_missing when the account has no card method. All are resolved by completing Stripe Connect onboarding for the organization.
The standard error body. error is a stable, machine-readable code — branch on it rather than on message, which is for humans and may change.
object
Machine-readable error code.
Human-readable detail.
Example
{ "error": "merchant_account_missing", "message": "The organization has no merchant account. Complete Stripe Connect onboarding for this organization before generating pricing."}