{
  "openapi": "3.1.0",
  "info": {
    "title": "Subcontext API",
    "version": "1",
    "summary": "Your products, quotes, leads and outcomes, for your own systems and pages.",
    "description": "The Subcontext API lets your firm's systems work with your Subcontext\norganisation: read your products, quote and sell them, send leads in,\nand report what became of them.\n\nEvery request needs an OAuth access token from your own API application,\nsent as `Authorization: Bearer <token>`. See\n[access tokens](https://subcontext.com/developers/oauth) for how to get\none, and which kind of application each request needs.\n\nEvery answer has the same shape: what you asked for in `data`, and\nerrors as `{ \"error\": { \"code\": \"...\", \"message\": \"...\", \"fields\": { ... } } }`,\nwith a message that says what to do (and, for a value that can't be\nused, `fields` naming it). Money is whole pence, in fields named `*_pence`. Times are ISO 8601. Lists page with `cursor` and `next_cursor`. [Conventions](https://subcontext.com/developers/api#conventions)\nhas the details.\n",
    "contact": {
      "name": "Subcontext",
      "email": "hello@subcontext.com",
      "url": "https://subcontext.com/developers"
    }
  },
  "servers": [
    {
      "url": "https://subcontext.com",
      "description": "Subcontext. There is one environment."
    }
  ],
  "security": [
    {
      "oauth2": [
        "read"
      ]
    },
    {
      "oauth2": [
        "write"
      ]
    }
  ],
  "tags": [
    {
      "name": "Products",
      "description": "Your organisation's products, as they're sold right now: the terms\ncustomers see (cooling-off period, what's included and excluded) and\nthe limits on the cover you can quote for (amounts, ages and terms).\n\nProducts come from the current release of each product, so changes\nyou're still working on in the dashboard don't show here until they're\npublished.\n"
    },
    {
      "name": "Journeys",
      "description": "A product's journeys: the sets of questions a customer answers to be\nquoted for it, such as a short \"express\" journey and a full one.\n\nThe questions endpoint gives you everything you need to draw your own\nform: the product with its cover limits, the journey, its questions in\norder with their answer options, and the presentation (the pages, or\nstages, the quote form shows them on). Browser and server-only\napplications can both call these.\n"
    },
    {
      "name": "Quotes and applications",
      "description": "An application is one customer's request for cover: their answers,\ntheir details and the cover they want. A quote prices it.\n\nThe usual order is to start an application, save the customer's answers\nand details as they give them, ask for a quote, and accept it. Then\ntake payment and set up the policy with the requests under\n[Checkout](/developers/api/reference/checkout). The guide\n[Quote and sell through the API](/developers/api/quote-and-sell) walks\nthrough it with examples.\n\nBrowser and server-only applications can both call these. Amounts are\nwhole pence (the smallest unit of the product's currency), in fields\nnamed `*_pence`.\n\nAnyone can get a browser application's token, so for one an\napplication's id isn't enough to reach it. Every request about an\napplication that already exists, and every Checkout request, also\nsends the application's `share_token` in the `X-Share-Token` header.\nKeep it from the answer that started the application. Without it, or\nwith another application's, the answer is `404 not_found`, the same\nas for an id that doesn't exist. A server-only application doesn't\nneed it.\n"
    },
    {
      "name": "Checkout",
      "description": "Turning an accepted quote into a policy: what the customer must see\nbefore they buy, their Direct Debit details, the first premium by card\n(through Stripe), and setting up the policy.\n\nEvery request here works on an issued quote that hasn't expired.\nBrowser and server-only applications can both call these. A browser\napplication sends the quote's application's `share_token` in the\n`X-Share-Token` header, as for\n[Quotes and applications](/developers/api/reference/quotes-and-applications).\n"
    },
    {
      "name": "Lookups",
      "description": "Help for your own forms: check a phone number as the customer types\nit, and find the addresses at a UK postcode. Browser and server-only\napplications can both call these.\n"
    },
    {
      "name": "CRM: leads",
      "x-server-only": true,
      "description": "Send leads in from your own systems or a partner's, and read what\nbecame of them: where each lead is now, and a feed of what has\nhappened to them.\n\nThese need a server-only application with the `crm` scope. An application only sees the leads it sent. The guide\n[Send leads and read what happened to them](/developers/api/leads)\nwalks through it.\n"
    },
    {
      "name": "CRM: outcomes",
      "x-server-only": true,
      "description": "Report what became of a lead after it left Subcontext: quoted, sold,\ncancelled, commission paid. Outcomes feed your organisation's reports\non what each campaign and source earns.\n\nThese need a server-only application with the `outcomes` scope (any\nlead in your organisation) or the `crm` scope (only the leads that\napplication sent). The guide [Report outcomes](/developers/api/outcomes)\nwalks through it.\n"
    },
    {
      "name": "Loyalty",
      "x-server-only": true,
      "description": "For a loyalty programme partner: read a membership, confirm a\npolicyholder's enrolment, suspend or cancel it, and send the points\nand tiers they earn.\n\nThese need a server-only application, with `write` for changes and `read` or `write` to read a membership. The\nguide [Loyalty partners](/developers/api/loyalty) walks through it.\n"
    },
    {
      "name": "Outreach",
      "x-server-only": true,
      "description": "Follow an outreach stream's progress: how many people it has reached,\non which channels, and how many replied, booked or bought.\n\nRead only, and for server-only applications. People reach a stream\nas leads (see [CRM: leads](/developers/api/reference/crm-leads)), never\nthrough this endpoint. The guide [Outreach streams](/developers/api/outreach)\nwalks through it.\n"
    }
  ],
  "paths": {
    "/api/v1/products": {
      "get": {
        "operationId": "listProducts",
        "tags": [
          "Products"
        ],
        "summary": "List your products",
        "description": "Every product your organisation makes, in name order, whatever its\nstate. Check `lifecycle_state` for the ones on sale (`production`).\n",
        "responses": {
          "200": {
            "description": "Your products.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The products, in name order.",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                      "display_id": "prod_0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                      "slug": "level-term-life",
                      "name": "Level Term Life",
                      "product_type": "term",
                      "currency_code": "GBP",
                      "lifecycle_state": "production",
                      "cooldown_days": 30,
                      "inclusions": [
                        "Terminal illness benefit, paid early if you're diagnosed with 12 months or less to live"
                      ],
                      "exclusions": [
                        "Death caused by a deliberately self-inflicted injury in the first year"
                      ],
                      "cover_bounds": {
                        "sum_assured_min_pence": 1000000,
                        "sum_assured_max_pence": 50000000,
                        "age_min": 18,
                        "age_max": 65,
                        "term_min": 5,
                        "term_max": 40
                      },
                      "covers": [
                        {
                          "id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                          "display_id": "cov_0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                          "cover_type": "life",
                          "cover_index": 0,
                          "sum_assured_min_pence": 1000000,
                          "sum_assured_max_pence": 50000000,
                          "age_at_entry_min": 18,
                          "age_at_entry_max": 65,
                          "term_years_min": 5,
                          "term_years_max": 40,
                          "max_age_at_expiry": 80,
                          "premium_basis": "guaranteed",
                          "review_period_years": null,
                          "minimum_premium_pence": 500,
                          "ci_payout_basis": "additional",
                          "survival_period_days": 14,
                          "indexation_method": "none",
                          "benefit_basis": "lump_sum",
                          "title": null,
                          "pricing_basis": "rated",
                          "member_premium_pence": null,
                          "members_factor": null,
                          "opt_in_factor": null
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/products/{slug}": {
      "get": {
        "operationId": "getProduct",
        "tags": [
          "Products"
        ],
        "summary": "Get a product",
        "description": "One of your organisation's products, found by its slug.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProductSlug"
          }
        ],
        "responses": {
          "200": {
            "description": "The product.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "display_id": "prod_0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "slug": "level-term-life",
                    "name": "Level Term Life",
                    "product_type": "term",
                    "currency_code": "GBP",
                    "lifecycle_state": "production",
                    "cooldown_days": 30,
                    "inclusions": [
                      "Terminal illness benefit, paid early if you're diagnosed with 12 months or less to live"
                    ],
                    "exclusions": [
                      "Death caused by a deliberately self-inflicted injury in the first year"
                    ],
                    "cover_bounds": {
                      "sum_assured_min_pence": 1000000,
                      "sum_assured_max_pence": 50000000,
                      "age_min": 18,
                      "age_max": 65,
                      "term_min": 5,
                      "term_max": 40
                    },
                    "covers": [
                      {
                        "id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                        "display_id": "cov_0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                        "cover_type": "life",
                        "cover_index": 0,
                        "sum_assured_min_pence": 1000000,
                        "sum_assured_max_pence": 50000000,
                        "age_at_entry_min": 18,
                        "age_at_entry_max": 65,
                        "term_years_min": 5,
                        "term_years_max": 40,
                        "max_age_at_expiry": 80,
                        "premium_basis": "guaranteed",
                        "review_period_years": null,
                        "minimum_premium_pence": 500,
                        "ci_payout_basis": "additional",
                        "survival_period_days": 14,
                        "indexation_method": "none",
                        "benefit_basis": "lump_sum",
                        "title": null,
                        "pricing_basis": "rated",
                        "member_premium_pence": null,
                        "members_factor": null,
                        "opt_in_factor": null
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/products/{product_slug}/journeys": {
      "get": {
        "operationId": "listJourneys",
        "tags": [
          "Journeys"
        ],
        "summary": "List a product's journeys",
        "description": "Every journey on one of your products, in the order they're arranged\nin the dashboard, whatever their state. Use a journey's `slug` to\nget its questions, and to start an application.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProductSlugPath"
          }
        ],
        "responses": {
          "200": {
            "description": "The product's journeys.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The journeys, in order.",
                      "items": {
                        "$ref": "#/components/schemas/Journey"
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                      "display_id": "jrn_0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                      "slug": "express",
                      "name": "Quick quote",
                      "description": "A few questions and a price in two minutes.",
                      "journey_loading": "1.00",
                      "position": 0,
                      "lifecycle_state": "production"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/products/{product_slug}/journeys/{slug}": {
      "get": {
        "operationId": "getJourney",
        "tags": [
          "Journeys"
        ],
        "summary": "Get a journey",
        "description": "One journey on one of your products, found by its slug.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProductSlugPath"
          },
          {
            "$ref": "#/components/parameters/JourneySlug"
          }
        ],
        "responses": {
          "200": {
            "description": "The journey.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Journey"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "display_id": "jrn_0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "slug": "express",
                    "name": "Quick quote",
                    "description": "A few questions and a price in two minutes.",
                    "journey_loading": "1.00",
                    "position": 0,
                    "lifecycle_state": "production"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/products/{product_slug}/journeys/{slug}/questions": {
      "get": {
        "operationId": "getJourneyQuestions",
        "tags": [
          "Journeys"
        ],
        "summary": "Get a journey's questions",
        "description": "Everything a form needs to ask for a quote: the product (with its\ncover limits, so you can check amounts, ages and terms before you\nask for a price), the journey, its questions in order, and the\npresentation that arranges them into pages.\n\nThe questions are the ones from the product's current release.\nPass `application_id` when you're picking up an application that's\nalready started. You get the questions it was started with, even\nif the product has been published again since.\n\nA question with `ask_if` is only asked when the answers so far meet\nits condition. An answer option with a `terminal_outcome` ends the\napplication there (for example \"Do you live in the UK?\" answered\n\"No\" declines), so a form can say so straight away.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProductSlugPath"
          },
          {
            "$ref": "#/components/parameters/JourneySlug"
          },
          {
            "name": "presentation_slug",
            "in": "query",
            "required": false,
            "description": "Which of the journey's presentations to use, by its address\nslug. Leave it out for the journey's default presentation (an\nunknown slug also gives the default).\n",
            "schema": {
              "type": "string"
            },
            "example": "standard"
          },
          {
            "name": "application_id",
            "in": "query",
            "required": false,
            "description": "An application already under way on this journey. Its questions\nand presentation are the ones it started with. An id that isn't\none of yours, or is on another journey, is ignored. So is one a\nbrowser application sends without the application's\n`share_token` in `X-Share-Token`.\n",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "The product, journey, questions and presentation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "product",
                        "journey",
                        "questions",
                        "presentation"
                      ],
                      "properties": {
                        "product": {
                          "$ref": "#/components/schemas/Product"
                        },
                        "journey": {
                          "$ref": "#/components/schemas/Journey"
                        },
                        "questions": {
                          "type": "array",
                          "description": "The journey's questions, in the order they're asked.",
                          "items": {
                            "$ref": "#/components/schemas/Question"
                          }
                        },
                        "presentation": {
                          "description": "How the questions are arranged into pages, or `null` when the journey has no presentation.",
                          "anyOf": [
                            {
                              "$ref": "#/components/schemas/Presentation"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "product": {
                      "id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                      "display_id": "prod_0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                      "slug": "level-term-life",
                      "name": "Level Term Life",
                      "product_type": "term",
                      "currency_code": "GBP",
                      "lifecycle_state": "production",
                      "cooldown_days": 30,
                      "inclusions": [
                        "Terminal illness benefit, paid early if you're diagnosed with 12 months or less to live"
                      ],
                      "exclusions": [
                        "Death caused by a deliberately self-inflicted injury in the first year"
                      ],
                      "cover_bounds": {
                        "sum_assured_min_pence": 1000000,
                        "sum_assured_max_pence": 50000000,
                        "age_min": 18,
                        "age_max": 65,
                        "term_min": 5,
                        "term_max": 40
                      },
                      "covers": [
                        {
                          "id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                          "display_id": "cov_0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                          "cover_type": "life",
                          "cover_index": 0,
                          "sum_assured_min_pence": 1000000,
                          "sum_assured_max_pence": 50000000,
                          "age_at_entry_min": 18,
                          "age_at_entry_max": 65,
                          "term_years_min": 5,
                          "term_years_max": 40,
                          "max_age_at_expiry": 80,
                          "premium_basis": "guaranteed",
                          "review_period_years": null,
                          "minimum_premium_pence": 500,
                          "ci_payout_basis": "additional",
                          "survival_period_days": 14,
                          "indexation_method": "none",
                          "benefit_basis": "lump_sum",
                          "title": null,
                          "pricing_basis": "rated",
                          "member_premium_pence": null,
                          "members_factor": null,
                          "opt_in_factor": null
                        }
                      ]
                    },
                    "journey": {
                      "id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                      "display_id": "jrn_0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                      "slug": "express",
                      "name": "Quick quote",
                      "description": "A few questions and a price in two minutes.",
                      "journey_loading": "1.00",
                      "position": 0,
                      "lifecycle_state": "production"
                    },
                    "questions": [
                      {
                        "id": "0199a3c2-6b20-7a11-9f3e-1c2d3e4f5a61",
                        "display_id": "qst_0199a3c2-6b20-7a11-9f3e-1c2d3e4f5a61",
                        "key": "uk_resident",
                        "label": "Do you live in the UK?",
                        "help_text": null,
                        "question_type": "enum",
                        "position": 0,
                        "required": true,
                        "validation": {},
                        "group_key": null,
                        "group_label": null,
                        "lookup_source": null,
                        "suggestions": null,
                        "answer_options": [
                          {
                            "id": "0199a3c2-6b21-7c40-8e5a-4b3c2d1e0f72",
                            "value": "yes",
                            "label": "Yes",
                            "position": 0
                          },
                          {
                            "id": "0199a3c2-6b22-7d51-9f6b-5c4d3e2f1083",
                            "value": "no",
                            "label": "No",
                            "position": 1,
                            "terminal_outcome": "decline",
                            "terminal_reason_code": "not_uk_resident",
                            "terminal_reason_message": "We can only cover people who live in the UK."
                          }
                        ]
                      },
                      {
                        "id": "0199a3c2-6b30-7b22-8a4f-2d3e4f5a6b72",
                        "display_id": "qst_0199a3c2-6b30-7b22-8a4f-2d3e4f5a6b72",
                        "key": "smoker",
                        "label": "Have you smoked or used nicotine in the last 12 months?",
                        "help_text": "Including vapes and nicotine patches.",
                        "question_type": "boolean",
                        "position": 1,
                        "required": true,
                        "validation": {},
                        "group_key": "lifestyle",
                        "group_label": "Your lifestyle",
                        "lookup_source": null,
                        "suggestions": null,
                        "answer_options": []
                      },
                      {
                        "id": "0199a3c2-6b40-7c33-9b5a-3e4f5a6b7c83",
                        "display_id": "qst_0199a3c2-6b40-7c33-9b5a-3e4f5a6b7c83",
                        "key": "cigarettes_per_day",
                        "label": "How many cigarettes a day?",
                        "help_text": null,
                        "question_type": "integer",
                        "position": 2,
                        "required": true,
                        "validation": {
                          "min": 1,
                          "max": 100
                        },
                        "group_key": "lifestyle",
                        "group_label": "Your lifestyle",
                        "lookup_source": null,
                        "suggestions": null,
                        "answer_options": [],
                        "ask_if": {
                          "key": "smoker",
                          "equals": true
                        }
                      }
                    ],
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/applications": {
      "post": {
        "operationId": "createApplication",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Start an application",
        "description": "Starts an application for one of your products, on one of its\njourneys. Start it as soon as the customer begins, so their answers\ncan be saved as they go.\n\nYou can start it without a customer (it's `anonymous` until you\nadd one with [Save the customer's details](/developers/api/reference/quotes-and-applications#saveApplicationCustomer)),\nor with one (it's `in_capture`). Answers you already have can go in\n`answers`.\n\nThe answer includes the application's `share_token`. Keep it. It's the key to the application for the quote form and the webchat, and\na browser application only sees it here. A browser application\nsends it in the `X-Share-Token` header with every later request\nabout the application.\n\n**Idempotency:** send an `Idempotency-Key` header (or\n`idempotency_key` in the body). Sending the same key again with the\nsame inputs gives back the application it started, with `200 OK`,\nrather than starting a second one. The same key with a different\nproduct, journey, presentation or customer (by email), or an answer\nthe application already holds a different value for, is refused\nwith `409 idempotency_key_conflict`.\n\nA browser application gets the `share_token` only on the request\nthat started the application, not on a replay. Keep it from the first answer. A server-only\napplication gets it every time.\n\nA browser application's tokens are effectively public and a key can\nbe guessed, so its replay must send the application's `share_token`\nin `X-Share-Token`, as with any request about the application.\nWithout it the answer is `409 idempotency_replay_unproven` and\nnothing is read or changed. If the first answer never arrived (so\nyou have no `share_token`), send the request again with a new key,\nand the old one in `replaces_idempotency_key`. The application the\nold key started is then closed (`abandoned`, reason\n`superseded_by_retry`), so nobody follows it up. A token handed out\nfor one application replays only that one.\n\nA `customer` whose email matches an existing customer is that\ncustomer, but a browser application never changes their record:\nsee [Save the customer's details](/developers/api/reference/quotes-and-applications#saveApplicationCustomer).\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product_slug",
                  "journey_slug"
                ],
                "properties": {
                  "product_slug": {
                    "type": "string",
                    "description": "The product's slug."
                  },
                  "journey_slug": {
                    "type": "string",
                    "description": "The journey's slug."
                  },
                  "presentation_slug": {
                    "type": "string",
                    "description": "Which of the journey's presentations to use. Leave it out for the default."
                  },
                  "answers": {
                    "type": "object",
                    "description": "Answers you already have, by question key (see [Get a journey's questions](/developers/api/reference/journeys#getJourneyQuestions)).",
                    "additionalProperties": true
                  },
                  "customer": {
                    "$ref": "#/components/schemas/CustomerInput"
                  },
                  "consent_answers": {
                    "type": "object",
                    "description": "When you send `customer`, the opt-out boxes from the\ndetails stage's `consent_opt_outs` the person ticked, by\nkey, as `false` (they said no to it).\n",
                    "additionalProperties": {
                      "type": "boolean"
                    }
                  },
                  "provenance": {
                    "$ref": "#/components/schemas/ProvenanceInput"
                  },
                  "idempotency_key": {
                    "type": "string",
                    "description": "The same as the `Idempotency-Key` header, for clients that can't set headers."
                  },
                  "replaces_idempotency_key": {
                    "$ref": "#/components/schemas/ReplacesIdempotencyKey"
                  },
                  "outreach_landing": {
                    "type": "string",
                    "description": "The token an outreach stream's link added to the page\n(its `ol` parameter), when the quote was started from\none. The quote counts as that person engaging, which can\nstop a sequence's later messages. A token that isn't\nvalid for your organisation is ignored.\n"
                  }
                }
              },
              "example": {
                "product_slug": "level-term-life",
                "journey_slug": "express",
                "answers": {
                  "uk_resident": "yes"
                },
                "provenance": {
                  "page_url": "https://www.example.com/life-cover?utm_source=newsletter",
                  "referrer": "https://www.google.com/"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The application was started.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "anonymous",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": null,
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes"
                    },
                    "cover_amount_pence": null,
                    "term_years": null,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:15:00+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "200": {
            "description": "An application was already started with this idempotency key and\nthe same inputs. This is it, as it is now (with `share_token` only\nfor a server-only application).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "anonymous",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": null,
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes"
                    },
                    "cover_amount_pence": null,
                    "term_years": null,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:15:00+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "- `idempotency_key_conflict`: the `Idempotency-Key` started an\n  application with different inputs. The message names them.\n- `idempotency_replay_unproven`: a browser application sent an\n  `Idempotency-Key` that already started an application, without\n  that application's `share_token` in `X-Share-Token`. Nothing\n  changed. Send the `share_token`, or start again with a new key.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "idempotency_key_conflict",
                    "message": "Idempotency-Key 'quote-0001' has already been used with different inputs (journey_slug, answers)."
                  }
                }
              }
            }
          },
          "422": {
            "description": "The request can't be used as sent (`fields` names what to change):\n\n- `validation_failed`: `product_slug` or `journey_slug` is missing.\n- `customer_invalid`: the customer's details aren't valid, for example a malformed email address.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "customer_invalid",
                    "message": "Email is invalid",
                    "fields": {
                      "customer.email": "is invalid"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}": {
      "get": {
        "operationId": "getApplication",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Get an application",
        "description": "The application as it is now: its status, answers, customer, cover\nand, for a whole-of-market product, the comparison's progress.\n\n`share_token` is only included for a server-only application (or a\ntoken handed out for this one application).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "The application.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "quoted",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": {
                      "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                      "title": "Ms",
                      "first_name": "Ada",
                      "last_name": "Lovelace",
                      "email": "ada@example.com",
                      "phone_number": "+447700900123",
                      "dob": "1988-04-12",
                      "postal_code": "SW1A 2AA",
                      "address_line1": "10 Example Street",
                      "address_line2": null,
                      "city": "London",
                      "country": "United Kingdom"
                    },
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes",
                      "smoker": false
                    },
                    "cover_amount_pence": 25000000,
                    "term_years": 25,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:19:42+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          }
        }
      }
    },
    "/api/v1/applications/{id}/answers": {
      "patch": {
        "operationId": "saveApplicationAnswers",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Save answers",
        "description": "Saves some of the customer's answers, by question key. Send what they've just answered (each page of your form, for example). Answers you've saved before are kept unless you send them again.\n\nTwo keys set the cover rather than answer a question:\n`sum_assured` (the amount of cover, in pence) and `term_years`.\n\nThe answer says which questions have been answered (`captured_keys`),\nwhich are still to ask (`missing_keys`) and, in `knockout`, any answer that means the application can't go on (for example a decline), so you can tell the customer.\n\nAn application that was declined, postponed or referred on earlier\nanswers is opened again, and the new answers are a fresh attempt.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "answers"
                ],
                "properties": {
                  "answers": {
                    "type": "object",
                    "description": "Answers by question key. Numbers as numbers, choices as the option's `value`, several choices as an array.",
                    "additionalProperties": true
                  },
                  "marketing_metadata": {
                    "type": "object",
                    "description": "Extra details to keep with the application that don't affect the price (for example the mortgage type).",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "answers": {
                  "smoker": false,
                  "sum_assured": 25000000,
                  "term_years": 25
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The answers were saved.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "application",
                        "captured_keys",
                        "missing_keys",
                        "knockout"
                      ],
                      "properties": {
                        "application": {
                          "$ref": "#/components/schemas/Application"
                        },
                        "captured_keys": {
                          "type": "array",
                          "description": "The question keys answered in this request.",
                          "items": {
                            "type": "string"
                          }
                        },
                        "missing_keys": {
                          "type": "array",
                          "description": "The questions still to answer (those that apply, given the answers so far).",
                          "items": {
                            "type": "string"
                          }
                        },
                        "knockout": {
                          "description": "When an answer on the application ends it, what it was; otherwise `null`.",
                          "anyOf": [
                            {
                              "$ref": "#/components/schemas/Knockout"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "application": {
                      "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "status": "quoted",
                      "idempotency_key": "quote-0001",
                      "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                      "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                      "customer": {
                        "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                        "title": "Ms",
                        "first_name": "Ada",
                        "last_name": "Lovelace",
                        "email": "ada@example.com",
                        "phone_number": "+447700900123",
                        "dob": "1988-04-12",
                        "postal_code": "SW1A 2AA",
                        "address_line1": "10 Example Street",
                        "address_line2": null,
                        "city": "London",
                        "country": "United Kingdom"
                      },
                      "joint_customer": null,
                      "risk_factors": {
                        "uk_resident": "yes",
                        "smoker": false
                      },
                      "cover_amount_pence": 25000000,
                      "term_years": 25,
                      "policy_id": null,
                      "abandoned_reason": null,
                      "presentation": {
                        "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "slug": "standard",
                        "name": "Standard",
                        "template_key": "standard",
                        "is_default": true,
                        "stages": [
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                            "key": "details",
                            "position": 1,
                            "stage_type": "personal_details",
                            "title": "Your details",
                            "cta_label": null,
                            "config": {
                              "fields": [
                                "first_name",
                                "last_name",
                                "email",
                                "phone",
                                "dob",
                                "address"
                              ]
                            },
                            "consent_notice": "We'll use these details to give you your quote and set up your policy."
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                            "key": "cover",
                            "position": 2,
                            "stage_type": "cover_capture",
                            "title": "Cover",
                            "cta_label": null,
                            "config": {}
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                            "key": "health_questions",
                            "position": 3,
                            "stage_type": "questions",
                            "title": "Health questions",
                            "cta_label": null,
                            "config": {
                              "all_remaining": true
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                            "key": "quote",
                            "position": 4,
                            "stage_type": "quote",
                            "title": "Your quote",
                            "cta_label": "Buy your policy",
                            "config": {
                              "label": "final"
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                            "key": "payment",
                            "position": 5,
                            "stage_type": "payment",
                            "title": "Payment",
                            "cta_label": null,
                            "config": {}
                          }
                        ]
                      },
                      "inline_bacs_mandate": false,
                      "direct_debit_first": false,
                      "stripe_test_mode": false,
                      "market_quotes": null,
                      "marketing_answered": false,
                      "created_at": "2026-10-12T10:15:00+01:00",
                      "updated_at": "2026-10-12T10:19:42+01:00",
                      "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                    },
                    "captured_keys": [
                      "smoker"
                    ],
                    "missing_keys": [
                      "weight_kg",
                      "height_cm"
                    ],
                    "knockout": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "422": {
            "description": "The answers weren't saved:\n\n- `answers_invalid`: a key isn't one of the journey's questions,\n  or a value doesn't fit its question (`fields` names each, by\n  question key, and says why), or the application can't take\n  answers any more (it's bound or abandoned).\n- `validation_failed`: `answers` is missing.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "answers_invalid",
                    "message": "invalid answers: cigarettes_per_day must be at most 100",
                    "fields": {
                      "cigarettes_per_day": "must be at most 100"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/customer": {
      "patch": {
        "operationId": "saveApplicationCustomer",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Save the customer's details",
        "description": "Adds the customer (the person to be covered) to the application, or\nupdates them. Customers are found by email address within your\norganisation, so the same person applying twice is one customer.\n\nAnyone can type anyone's email address, so a customer who's already\non record isn't always updated:\n\n- A server-only application updates them, except a policyholder,\n  whose record only gains the details it's missing.\n- A browser application never changes an existing customer's record,\n  unless the customer was created by this application (by Start an\n  application, Quote in one request or this request). Otherwise the\n  application is theirs, but what was typed is kept on the\n  application.\n\nWhen details are kept off the record, the answer shows what was typed,\nand quotes for the application are priced on it. Your staff still see\nthe stored record.\n\nAn `anonymous` application moves to `in_capture`. A quoted or referred one keeps its status. `consent_answers` records any opt-out\nboxes the person ticked on the details page.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "customer"
                ],
                "properties": {
                  "customer": {
                    "$ref": "#/components/schemas/CustomerInput"
                  },
                  "consent_answers": {
                    "type": "object",
                    "description": "The details stage's opt-out boxes the person ticked, by key, as `false`.",
                    "additionalProperties": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "example": {
                "customer": {
                  "title": "Ms",
                  "first_name": "Ada",
                  "last_name": "Lovelace",
                  "email": "ada@example.com",
                  "phone_number": "+447700900123",
                  "dob": "1988-04-12",
                  "postal_code": "SW1A 2AA",
                  "address_line1": "10 Example Street",
                  "city": "London",
                  "country": "United Kingdom"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The customer was saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "quoted",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": {
                      "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                      "title": "Ms",
                      "first_name": "Ada",
                      "last_name": "Lovelace",
                      "email": "ada@example.com",
                      "phone_number": "+447700900123",
                      "dob": "1988-04-12",
                      "postal_code": "SW1A 2AA",
                      "address_line1": "10 Example Street",
                      "address_line2": null,
                      "city": "London",
                      "country": "United Kingdom"
                    },
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes",
                      "smoker": false
                    },
                    "cover_amount_pence": 25000000,
                    "term_years": 25,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:19:42+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "422": {
            "description": "- `customer_invalid`: the details aren't valid (`fields` names each, as `customer.first_name`).\n- `validation_failed`: `customer` is missing.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "customer_invalid",
                    "message": "First name can't be blank",
                    "fields": {
                      "customer.first_name": "can't be blank"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/partner": {
      "patch": {
        "operationId": "saveApplicationPartner",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Save the second person's details",
        "description": "For joint cover, adds the second person to be covered, or updates\nthem. Only for an application on a joint basis. An existing customer\nfound by email is treated as in [Save the customer's details](/developers/api/reference/quotes-and-applications#saveApplicationCustomer).\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "partner"
                ],
                "properties": {
                  "partner": {
                    "type": "object",
                    "description": "The second person.",
                    "properties": {
                      "title": {
                        "type": "string"
                      },
                      "first_name": {
                        "type": "string"
                      },
                      "last_name": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string",
                        "description": "Optional. Couples often share one address, so it may be the same as the first person's."
                      },
                      "phone_number": {
                        "type": "string"
                      },
                      "dob": {
                        "type": "string",
                        "format": "date",
                        "description": "Date of birth, `YYYY-MM-DD`."
                      }
                    }
                  }
                }
              },
              "example": {
                "partner": {
                  "first_name": "Charles",
                  "last_name": "Babbage",
                  "dob": "1986-12-26"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The second person was saved. They're the application's `joint_customer`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "quoted",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": {
                      "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                      "title": "Ms",
                      "first_name": "Ada",
                      "last_name": "Lovelace",
                      "email": "ada@example.com",
                      "phone_number": "+447700900123",
                      "dob": "1988-04-12",
                      "postal_code": "SW1A 2AA",
                      "address_line1": "10 Example Street",
                      "address_line2": null,
                      "city": "London",
                      "country": "United Kingdom"
                    },
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes",
                      "smoker": false
                    },
                    "cover_amount_pence": 25000000,
                    "term_years": 25,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:19:42+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "422": {
            "description": "- `not_joint_basis`: the application is for one person.\n- `partner_invalid`: the details aren't valid (`fields` names each, as `partner.dob`).\n- `validation_failed`: `partner` is missing.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_joint_basis",
                    "message": "application is not on a joint basis"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/soft_customer": {
      "patch": {
        "operationId": "saveApplicationSoftCustomer",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Save early details",
        "description": "For a presentation with a \"soft identity\" stage, saves the few\ndetails a customer gives early on (often a first name and a\npostcode) without making them a customer yet. They fill in the\ndetails stage later, and the quote form and webchat can greet the\nperson by name in the meantime.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "customer"
                ],
                "properties": {
                  "customer": {
                    "$ref": "#/components/schemas/CustomerInput"
                  }
                }
              },
              "example": {
                "customer": {
                  "first_name": "Ada",
                  "postal_code": "SW1A 2AA"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The details were saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "anonymous",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": null,
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes"
                    },
                    "cover_amount_pence": null,
                    "term_years": null,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:15:00+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/api/v1/applications/{id}/interstitial_choice": {
      "patch": {
        "operationId": "saveInterstitialChoice",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Save a choice on an interstitial page",
        "description": "For a presentation with an interstitial stage (a page that offers\nthe customer a choice, such as \"Would you like to add critical\nillness cover?\"), records which option they chose, by its key. Name\nthe stage by its `stage_key` (or, for older forms, its\n`stage_position`).\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "choice_key"
                ],
                "properties": {
                  "choice_key": {
                    "type": "string",
                    "description": "The key of the option the customer chose."
                  },
                  "stage_key": {
                    "type": "string",
                    "description": "The stage's `key`."
                  },
                  "stage_position": {
                    "type": "integer",
                    "description": "The stage's `position`, if you don't have its key."
                  }
                }
              },
              "example": {
                "stage_key": "add_critical_illness",
                "choice_key": "yes"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The choice was saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "anonymous",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": null,
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes"
                    },
                    "cover_amount_pence": null,
                    "term_years": null,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:15:00+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not_found`: no such application (or, for a browser application,\nno `X-Share-Token` that matches it), or no stage on its\npresentation has that `stage_key` or `stage_position`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "No stage on this application's presentation has that stage_key or stage_position."
                  }
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed`: `choice_key` is missing or blank.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "validation_failed",
                    "message": "choice_key is required.",
                    "fields": {
                      "choice_key": "is required"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/reflection": {
      "patch": {
        "operationId": "saveReflection",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Save a reflection",
        "description": "For a presentation with a reflection stage (a page that asks an open\nquestion, such as \"What matters most to you about this cover?\"), saves the customer's answer. It's optional, so send an empty or missing `text` when they skip it.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "What the customer wrote."
                  }
                }
              },
              "example": {
                "text": "Making sure the mortgage is paid off if something happens to me."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The answer was saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "anonymous",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": null,
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes"
                    },
                    "cover_amount_pence": null,
                    "term_years": null,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:15:00+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          }
        }
      }
    },
    "/api/v1/applications/{id}/handoff": {
      "patch": {
        "operationId": "handOffApplication",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Ask for a person to follow up",
        "description": "The customer would rather talk to someone. The application becomes\n`referred`, and your team is told (it appears on the dashboard's\nescalations, and whoever is set up to hear about them is notified).\nAsking again does nothing more.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "The application is with your team.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "quoted",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": {
                      "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                      "title": "Ms",
                      "first_name": "Ada",
                      "last_name": "Lovelace",
                      "email": "ada@example.com",
                      "phone_number": "+447700900123",
                      "dob": "1988-04-12",
                      "postal_code": "SW1A 2AA",
                      "address_line1": "10 Example Street",
                      "address_line2": null,
                      "city": "London",
                      "country": "United Kingdom"
                    },
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes",
                      "smoker": false
                    },
                    "cover_amount_pence": 25000000,
                    "term_years": 25,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:19:42+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          }
        }
      }
    },
    "/api/v1/applications/{id}/quote": {
      "post": {
        "operationId": "quoteApplication",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Quote the application",
        "description": "Prices the application as it stands: the cover saved with\n[Save answers](/developers/api/reference/quotes-and-applications#saveApplicationAnswers)\n(`sum_assured` and `term_years`) and the answers so far. Use it for\na price part way through the form, and again at the end.\n\nA price part way through may rest on assumptions about questions not answered yet. The quote's `assumptions` lists them, and the price is\nonly indicative until they're answered. Asking again replaces the\nprevious quote.\n\n`quote` is `null` when the answers mean no price can be offered, and the application's `status` says why (`declined`, `postponed` or `referred`).\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "The application and its new quote.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "application",
                        "quote"
                      ],
                      "properties": {
                        "application": {
                          "$ref": "#/components/schemas/Application"
                        },
                        "quote": {
                          "description": "The new quote, or `null` when no price can be offered.",
                          "anyOf": [
                            {
                              "$ref": "#/components/schemas/Quote"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "application": {
                      "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "status": "quoted",
                      "idempotency_key": "quote-0001",
                      "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                      "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                      "customer": {
                        "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                        "title": "Ms",
                        "first_name": "Ada",
                        "last_name": "Lovelace",
                        "email": "ada@example.com",
                        "phone_number": "+447700900123",
                        "dob": "1988-04-12",
                        "postal_code": "SW1A 2AA",
                        "address_line1": "10 Example Street",
                        "address_line2": null,
                        "city": "London",
                        "country": "United Kingdom"
                      },
                      "joint_customer": null,
                      "risk_factors": {
                        "uk_resident": "yes",
                        "smoker": false
                      },
                      "cover_amount_pence": 25000000,
                      "term_years": 25,
                      "policy_id": null,
                      "abandoned_reason": null,
                      "presentation": {
                        "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "slug": "standard",
                        "name": "Standard",
                        "template_key": "standard",
                        "is_default": true,
                        "stages": [
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                            "key": "details",
                            "position": 1,
                            "stage_type": "personal_details",
                            "title": "Your details",
                            "cta_label": null,
                            "config": {
                              "fields": [
                                "first_name",
                                "last_name",
                                "email",
                                "phone",
                                "dob",
                                "address"
                              ]
                            },
                            "consent_notice": "We'll use these details to give you your quote and set up your policy."
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                            "key": "cover",
                            "position": 2,
                            "stage_type": "cover_capture",
                            "title": "Cover",
                            "cta_label": null,
                            "config": {}
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                            "key": "health_questions",
                            "position": 3,
                            "stage_type": "questions",
                            "title": "Health questions",
                            "cta_label": null,
                            "config": {
                              "all_remaining": true
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                            "key": "quote",
                            "position": 4,
                            "stage_type": "quote",
                            "title": "Your quote",
                            "cta_label": "Buy your policy",
                            "config": {
                              "label": "final"
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                            "key": "payment",
                            "position": 5,
                            "stage_type": "payment",
                            "title": "Payment",
                            "cta_label": null,
                            "config": {}
                          }
                        ]
                      },
                      "inline_bacs_mandate": false,
                      "direct_debit_first": false,
                      "stripe_test_mode": false,
                      "market_quotes": null,
                      "marketing_answered": false,
                      "created_at": "2026-10-12T10:15:00+01:00",
                      "updated_at": "2026-10-12T10:19:42+01:00",
                      "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                    },
                    "quote": {
                      "id": "0199a3c2-7c00-7a77-9f9e-7c8d9eafb0c7",
                      "display_id": "quo_0199a3c2-7c00-7a77-9f9e-7c8d9eafb0c7",
                      "reference": "QT-AB-P001-000042",
                      "status": "issued",
                      "basis": "single",
                      "decision": "accept_standard",
                      "currency_code": "GBP",
                      "total_premium_monthly_pence": 1245,
                      "policy_fee_pence": 0,
                      "bundle_discount_pence": 0,
                      "issued_at": "2026-10-12T10:19:42+01:00",
                      "expires_at": "2026-11-11T10:19:42+00:00",
                      "accepted_at": null,
                      "superseded_by_id": null,
                      "assumptions": [],
                      "components": [
                        {
                          "id": "0199a3c2-7c01-7b88-8a0f-8d9eafb0c1d8",
                          "display_id": "qco_0199a3c2-7c01-7b88-8a0f-8d9eafb0c1d8",
                          "cover_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                          "cover_type": "life",
                          "component_index": 0,
                          "sum_assured_pence": 25000000,
                          "term_years": 25,
                          "decision": "accept_standard",
                          "rating_pct": 100,
                          "premium_monthly_pence": 1245,
                          "premium_annual_pence": 14940,
                          "exclusions": [],
                          "reasons": [],
                          "lives": [],
                          "member_count": null,
                          "title": "Life"
                        }
                      ],
                      "premium_illustration": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "422": {
            "description": "No quote could be made:\n\n- `cover_missing`: the amount of cover or the term isn't saved yet.\n- `no_quotable_cover`: the product has no cover that can be priced.\n- `quote_failed`: pricing failed (the message says why).\n- `rate_unavailable`: the details are acceptable, but there's no price for them.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cover_missing",
                    "message": "application has no cover_amount_pence / term_years yet"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/accept_quote": {
      "post": {
        "operationId": "acceptQuote",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Accept the quote",
        "description": "The customer wants to go ahead with the quote. Records that they\naccepted it, so the webchat (if they're also chatting) knows too.\nSend `quote_id` to name the quote. Without it, the application's current quote is accepted. Accepting it again is fine.\n\nThen go on to [Checkout](/developers/api/reference/checkout).\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "quote_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "The quote to accept. Leave it out for the application's current quote."
                  }
                }
              },
              "example": {
                "quote_id": "0199a3c2-7c00-7a77-9f9e-7c8d9eafb0c7"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The quote is accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "quoted",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": {
                      "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                      "title": "Ms",
                      "first_name": "Ada",
                      "last_name": "Lovelace",
                      "email": "ada@example.com",
                      "phone_number": "+447700900123",
                      "dob": "1988-04-12",
                      "postal_code": "SW1A 2AA",
                      "address_line1": "10 Example Street",
                      "address_line2": null,
                      "city": "London",
                      "country": "United Kingdom"
                    },
                    "joint_customer": null,
                    "risk_factors": {
                      "uk_resident": "yes",
                      "smoker": false
                    },
                    "cover_amount_pence": 25000000,
                    "term_years": 25,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": {
                      "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                      "slug": "standard",
                      "name": "Standard",
                      "template_key": "standard",
                      "is_default": true,
                      "stages": [
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                          "key": "details",
                          "position": 1,
                          "stage_type": "personal_details",
                          "title": "Your details",
                          "cta_label": null,
                          "config": {
                            "fields": [
                              "first_name",
                              "last_name",
                              "email",
                              "phone",
                              "dob",
                              "address"
                            ]
                          },
                          "consent_notice": "We'll use these details to give you your quote and set up your policy."
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                          "key": "cover",
                          "position": 2,
                          "stage_type": "cover_capture",
                          "title": "Cover",
                          "cta_label": null,
                          "config": {}
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                          "key": "health_questions",
                          "position": 3,
                          "stage_type": "questions",
                          "title": "Health questions",
                          "cta_label": null,
                          "config": {
                            "all_remaining": true
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                          "key": "quote",
                          "position": 4,
                          "stage_type": "quote",
                          "title": "Your quote",
                          "cta_label": "Buy your policy",
                          "config": {
                            "label": "final"
                          }
                        },
                        {
                          "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                          "key": "payment",
                          "position": 5,
                          "stage_type": "payment",
                          "title": "Payment",
                          "cta_label": null,
                          "config": {}
                        }
                      ]
                    },
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": null,
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:19:42+01:00",
                    "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "422": {
            "description": "`accept_failed`: there's no quote yet, it can't be bought any\nmore (it expired or was replaced), or the answers have changed\nsince it was priced (quote again).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "accept_failed",
                    "message": "no quote to proceed with yet: create one first"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/market_quotes": {
      "post": {
        "operationId": "requestMarketQuotes",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Search the market",
        "description": "For a whole-of-market product, starts a search for quotes from\nproviders across the market, using the application's answers. The\nsearch takes a little while, so this answers straight away with the\napplication, whose `market_quotes.status` is `pending` or `fetching`.\nFetch the application (every few seconds) until it's `completed`\n(or `failed`).\n\nAsking again with the same answers gives back the same search rather\nthan starting another.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "The search has started (or was already under way). The application's `market_quotes` shows its progress.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "in_capture",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": {
                      "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                      "title": "Ms",
                      "first_name": "Ada",
                      "last_name": "Lovelace",
                      "email": "ada@example.com",
                      "phone_number": "+447700900123",
                      "dob": "1988-04-12",
                      "postal_code": "SW1A 2AA",
                      "address_line1": "10 Example Street",
                      "address_line2": null,
                      "city": "London",
                      "country": "United Kingdom"
                    },
                    "joint_customer": null,
                    "risk_factors": {
                      "sex": "female",
                      "smoker": false,
                      "occupation": "Software Engineer"
                    },
                    "cover_amount_pence": 25000000,
                    "term_years": 25,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": null,
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": {
                      "request_id": "0199a3c2-7d00-7c99-9b1a-9eafb0c1d2e9",
                      "status": "completed",
                      "fetched_at": "2026-10-12T10:21:03+01:00",
                      "expires_at": "2026-11-12T10:21:03+00:00",
                      "stale": false,
                      "provider_count": 2,
                      "failure_code": null,
                      "selected_result_id": null,
                      "results": [
                        {
                          "ordinal": 1,
                          "result_id": "0199a3c2-7d01-7daa-8c2b-afb0c1d2e3fa",
                          "provider_name": "Example Life",
                          "logo_url": null,
                          "product_name": "Example Life Protection",
                          "premium_pence": 1180,
                          "premium_monthly": "£11.80",
                          "plan_fee_pence": null,
                          "status": "success",
                          "status_reason": null,
                          "variations": [],
                          "features": [],
                          "evidence_required": false,
                          "further_underwriting": false,
                          "standard_or_underwritten": null,
                          "expiry_date": "2026-11-12",
                          "selected": false
                        }
                      ]
                    },
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:21:03+01:00"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "422": {
            "description": "The search couldn't start:\n\n- `not_market_product`: the product is priced by your own rates, not across the market. Use [Quote the application](/developers/api/reference/quotes-and-applications#quoteApplication).\n- `mapping_incomplete`: answers the providers need are missing (`fields` names each, as `answers.sex`).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "mapping_incomplete",
                    "message": "Missing inputs for market quoting: sex, smoker",
                    "fields": {
                      "answers.sex": "is needed to search the market",
                      "answers.smoker": "is needed to search the market"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/select_market_quote": {
      "post": {
        "operationId": "selectMarketQuote",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Choose a market quote",
        "description": "The customer has chosen one provider's quote from the market search.\nName it by its `result_id`. Then ask for the link that takes them to\nthe provider: [Get the link to the provider](/developers/api/reference/quotes-and-applications#createHandoffLink).\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "result_id"
                ],
                "properties": {
                  "result_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "The chosen result's `result_id`, from the application's `market_quotes.results`."
                  }
                }
              },
              "example": {
                "result_id": "0199a3c2-7d01-7daa-8c2b-afb0c1d2e3fa"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The choice is recorded. `market_quotes.selected_result_id` names it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                    "status": "in_capture",
                    "idempotency_key": "quote-0001",
                    "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                    "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                    "customer": {
                      "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                      "title": "Ms",
                      "first_name": "Ada",
                      "last_name": "Lovelace",
                      "email": "ada@example.com",
                      "phone_number": "+447700900123",
                      "dob": "1988-04-12",
                      "postal_code": "SW1A 2AA",
                      "address_line1": "10 Example Street",
                      "address_line2": null,
                      "city": "London",
                      "country": "United Kingdom"
                    },
                    "joint_customer": null,
                    "risk_factors": {
                      "sex": "female",
                      "smoker": false,
                      "occupation": "Software Engineer"
                    },
                    "cover_amount_pence": 25000000,
                    "term_years": 25,
                    "policy_id": null,
                    "abandoned_reason": null,
                    "presentation": null,
                    "inline_bacs_mandate": false,
                    "direct_debit_first": false,
                    "stripe_test_mode": false,
                    "market_quotes": {
                      "request_id": "0199a3c2-7d00-7c99-9b1a-9eafb0c1d2e9",
                      "status": "completed",
                      "fetched_at": "2026-10-12T10:21:03+01:00",
                      "expires_at": "2026-11-12T10:21:03+00:00",
                      "stale": false,
                      "provider_count": 2,
                      "failure_code": null,
                      "selected_result_id": null,
                      "results": [
                        {
                          "ordinal": 1,
                          "result_id": "0199a3c2-7d01-7daa-8c2b-afb0c1d2e3fa",
                          "provider_name": "Example Life",
                          "logo_url": null,
                          "product_name": "Example Life Protection",
                          "premium_pence": 1180,
                          "premium_monthly": "£11.80",
                          "plan_fee_pence": null,
                          "status": "success",
                          "status_reason": null,
                          "variations": [],
                          "features": [],
                          "evidence_required": false,
                          "further_underwriting": false,
                          "standard_or_underwritten": null,
                          "expiry_date": "2026-11-12",
                          "selected": false
                        }
                      ]
                    },
                    "marketing_answered": false,
                    "created_at": "2026-10-12T10:15:00+01:00",
                    "updated_at": "2026-10-12T10:21:03+01:00"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not_found`: no such application (or, for a browser application,\nno `X-Share-Token` that matches it), or no quote with that\n`result_id` on its search.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "No such quote on this application's market search."
                  }
                }
              }
            }
          },
          "409": {
            "description": "`results_stale`: the answers have changed since the search, or a\nnewer search replaced it. Search again.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "results_stale",
                    "message": "These results are out of date: refresh the market search"
                  }
                }
              }
            }
          },
          "422": {
            "description": "- `select_failed`: that provider didn't return a usable quote, the\n  search hasn't finished, or the quote has expired.\n- `validation_failed`: `result_id` is missing.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "select_failed",
                    "message": "This quote has expired: run a fresh market search"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/handoff_link": {
      "post": {
        "operationId": "createHandoffLink",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Get the link to the provider",
        "description": "After [Choose a market quote](/developers/api/reference/quotes-and-applications#selectMarketQuote), the link that takes the customer to the chosen provider to finish\ntheir application. The application becomes `handed_off`. Asking\nagain gives a fresh link for the same choice.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "The link, and the provider's name for your button.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "url",
                        "provider_name"
                      ],
                      "properties": {
                        "url": {
                          "type": "string",
                          "format": "uri",
                          "description": "Where to send the customer."
                        },
                        "provider_name": {
                          "type": "string",
                          "description": "The provider's name."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "url": "https://subcontext.com/handoff/eyJfcmFpbHMiOnsiZGF0YSI6e30sInB1ciI6Im1hcmtldF9oYW5kb2ZmIn19--3f1b2c",
                    "provider_name": "Example Life"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "422": {
            "description": "- `no_selection`: no market quote has been chosen yet.\n- `expired`: the chosen quote has expired. Search again.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "no_selection",
                    "message": "No market quote has been selected"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/marketing_preference": {
      "post": {
        "operationId": "recordMarketingPreference",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Record marketing choices",
        "description": "Records the customer's answer to your firm's marketing question (the\n`marketing` question on the quote and comparison stages, set under\nconsent in the dashboard): `true` for each option they agreed to,\n`false` for each they said no to. Leave out the options they didn't answer, because an untouched box isn't a no. A key that isn't one of the\nquestion's options is refused, and nothing is recorded.\n\nThe application needs a customer first.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "answers": {
                    "type": "object",
                    "description": "Each answered option's key, and whether they agreed.",
                    "additionalProperties": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "example": {
                "answers": {
                  "email": true,
                  "post": true,
                  "sms": false
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The choices are recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "agreed",
                        "declined"
                      ],
                      "properties": {
                        "agreed": {
                          "type": "array",
                          "description": "The options they agreed to.",
                          "items": {
                            "type": "string"
                          }
                        },
                        "declined": {
                          "type": "array",
                          "description": "The options they said no to.",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "agreed": [
                      "email",
                      "post"
                    ],
                    "declined": [
                      "sms"
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "422": {
            "description": "Nothing was recorded:\n\n- `customer_missing`: the application has no customer yet.\n- `validation_failed`: `answers` has a key that isn't one of the question's options (`fields` names it, as `answers.sms`), or isn't an object.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "customer_missing",
                    "message": "the application has no customer to record this for"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/applications/{id}/cable_ticket": {
      "post": {
        "operationId": "createCableTicket",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Get a live updates ticket",
        "description": "For pages that show an application's changes as they happen (the quote form does, so a customer can fill it in while chatting), a short-lived ticket for opening the application's live updates\nconnection. Prove you hold the application by sending its\n`share_token` in the body. For a browser application that body\nvalue also counts as the `X-Share-Token` header. The ticket lasts\ntwo hours; ask for a new one each time you connect.\n\nYou only need this if you're building your own live view. Fetching\nthe application now and then does the same job more simply.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApplicationId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "application_share_token"
                ],
                "properties": {
                  "application_share_token": {
                    "type": "string",
                    "description": "The application's `share_token`."
                  }
                }
              },
              "example": {
                "application_share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The ticket.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "ticket",
                        "expires_in"
                      ],
                      "properties": {
                        "ticket": {
                          "type": "string",
                          "description": "The ticket. Treat it like a password."
                        },
                        "expires_in": {
                          "type": "integer",
                          "description": "How many seconds it lasts."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "ticket": "eyJfcmFpbHMiOnsiZGF0YSI6eyJhcHBsaWNhdGlvbl9pZCI6IjAxOTkifX19--46dfd79138c98ea6",
                    "expires_in": 7200
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`forbidden`: the token can't be used here (a missing scope, or the wrong kind of application or website), or the `share_token` isn't this application's.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "forbidden",
                    "message": "application_share_token isn't this application's."
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          }
        }
      }
    },
    "/api/v1/quotes": {
      "post": {
        "operationId": "createQuote",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Quote in one request",
        "description": "Prices cover in a single request. You send the customer, their answers and the cover they want, and get back the application and its quote. Use it when your own system already has everything. To build an application up as the customer goes, use [Start an application](/developers/api/reference/quotes-and-applications#createApplication) and the requests after it.\n\n`components` lists the cover wanted. Each names a cover by\n`cover_type` (the product's first cover of that type) or `cover_id`,\nwith the amount in whole pence (`sum_assured_pence`) and the term in\nwhole years. Amounts, ages and terms are checked against the\nproduct's limits.\n\nSend `application_id` to quote an application you started earlier. A browser application sends that application's `share_token` in `X-Share-Token` too. Changed answers or cover give a new quote. A bound application is\nreturned as it is. If that application already has a customer, the\n`customer` you send must be the same person (by email).\n\n**Idempotency:** send an `Idempotency-Key` header. A retry with the\nsame key and the same inputs gives back the same application and\nquote (`200 OK`). The same key with different inputs is refused (`409`).\nA browser application's retry must send the application's\n`share_token` in `X-Share-Token`: without it the answer is\n`409 idempotency_replay_unproven`, and neither the application nor\nthe customer is touched. If the first answer never arrived, send the\nrequest again with a new key, and the old one in\n`replaces_idempotency_key`: the application the old key made is\nclosed (`abandoned`, reason `superseded_by_retry`) and its quote\nwithdrawn, so nobody follows it up.\n\nA `customer` whose email matches an existing customer is that\ncustomer, but a browser application never changes their record:\nwhat it sends is kept on the application, shown back and priced on\n(see [Save the customer's details](/developers/api/reference/quotes-and-applications#saveApplicationCustomer)).\n\nThe application's `share_token` comes with a new application\n(`201`). An application that already existed (`200`, found by\n`Idempotency-Key` or `application_id`) shows it only to a\nserver-only application, or a token handed out for that one\napplication, as [Start an application](/developers/api/reference/quotes-and-applications#createApplication)\ndoes on a replay.\n\n`quote` is `null` when the answers mean no price can be offered. The application's `status` says why, and `executions` has the detail.\nEach execution's `trace` (the steps of the assessment) is only for a server-only application.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product_slug",
                  "journey_slug",
                  "customer",
                  "components"
                ],
                "properties": {
                  "product_slug": {
                    "type": "string",
                    "description": "The product's slug."
                  },
                  "journey_slug": {
                    "type": "string",
                    "description": "The journey's slug."
                  },
                  "customer": {
                    "$ref": "#/components/schemas/CustomerInput"
                  },
                  "risk_factors": {
                    "type": "object",
                    "description": "The answers, by question key. Answers to the journey's\nquestions are checked as [Save answers](/developers/api/reference/quotes-and-applications#saveApplicationAnswers)\nchecks them; other keys are kept as they are.\n",
                    "additionalProperties": true
                  },
                  "components": {
                    "type": "array",
                    "description": "The cover wanted, at least one.",
                    "minItems": 1,
                    "items": {
                      "type": "object",
                      "required": [
                        "sum_assured_pence"
                      ],
                      "properties": {
                        "cover_type": {
                          "type": "string",
                          "description": "The kind of cover, such as `life` or `critical_illness`. Send this or `cover_id`."
                        },
                        "cover_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "A particular cover on the product, from [Get a product](/developers/api/reference/products#getProduct)."
                        },
                        "sum_assured_pence": {
                          "type": "integer",
                          "description": "The amount of cover, in whole pence (for a monthly benefit, the yearly amount)."
                        },
                        "term_years": {
                          "type": "integer",
                          "description": "The term in years. Leave it out for cover with no fixed term."
                        }
                      }
                    }
                  },
                  "application_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "An application you started earlier, to quote that one."
                  },
                  "idempotency_key": {
                    "type": "string",
                    "description": "The same as the `Idempotency-Key` header."
                  },
                  "replaces_idempotency_key": {
                    "$ref": "#/components/schemas/ReplacesIdempotencyKey"
                  }
                }
              },
              "example": {
                "product_slug": "level-term-life",
                "journey_slug": "express",
                "customer": {
                  "first_name": "Ada",
                  "last_name": "Lovelace",
                  "email": "ada@example.com",
                  "dob": "1988-04-12",
                  "postal_code": "SW1A 2AA"
                },
                "risk_factors": {
                  "uk_resident": "yes",
                  "smoker": false
                },
                "components": [
                  {
                    "cover_type": "life",
                    "sum_assured_pence": 25000000,
                    "term_years": 25
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "A new application was made and quoted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResult"
                },
                "example": {
                  "data": {
                    "application": {
                      "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "status": "quoted",
                      "idempotency_key": "quote-0001",
                      "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                      "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                      "customer": {
                        "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                        "title": "Ms",
                        "first_name": "Ada",
                        "last_name": "Lovelace",
                        "email": "ada@example.com",
                        "phone_number": "+447700900123",
                        "dob": "1988-04-12",
                        "postal_code": "SW1A 2AA",
                        "address_line1": "10 Example Street",
                        "address_line2": null,
                        "city": "London",
                        "country": "United Kingdom"
                      },
                      "joint_customer": null,
                      "risk_factors": {
                        "uk_resident": "yes",
                        "smoker": false
                      },
                      "cover_amount_pence": 25000000,
                      "term_years": 25,
                      "policy_id": null,
                      "abandoned_reason": null,
                      "presentation": {
                        "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "slug": "standard",
                        "name": "Standard",
                        "template_key": "standard",
                        "is_default": true,
                        "stages": [
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                            "key": "details",
                            "position": 1,
                            "stage_type": "personal_details",
                            "title": "Your details",
                            "cta_label": null,
                            "config": {
                              "fields": [
                                "first_name",
                                "last_name",
                                "email",
                                "phone",
                                "dob",
                                "address"
                              ]
                            },
                            "consent_notice": "We'll use these details to give you your quote and set up your policy."
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                            "key": "cover",
                            "position": 2,
                            "stage_type": "cover_capture",
                            "title": "Cover",
                            "cta_label": null,
                            "config": {}
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                            "key": "health_questions",
                            "position": 3,
                            "stage_type": "questions",
                            "title": "Health questions",
                            "cta_label": null,
                            "config": {
                              "all_remaining": true
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                            "key": "quote",
                            "position": 4,
                            "stage_type": "quote",
                            "title": "Your quote",
                            "cta_label": "Buy your policy",
                            "config": {
                              "label": "final"
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                            "key": "payment",
                            "position": 5,
                            "stage_type": "payment",
                            "title": "Payment",
                            "cta_label": null,
                            "config": {}
                          }
                        ]
                      },
                      "inline_bacs_mandate": false,
                      "direct_debit_first": false,
                      "stripe_test_mode": false,
                      "market_quotes": null,
                      "marketing_answered": false,
                      "created_at": "2026-10-12T10:15:00+01:00",
                      "updated_at": "2026-10-12T10:19:42+01:00",
                      "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                    },
                    "quote": {
                      "id": "0199a3c2-7c00-7a77-9f9e-7c8d9eafb0c7",
                      "display_id": "quo_0199a3c2-7c00-7a77-9f9e-7c8d9eafb0c7",
                      "reference": "QT-AB-P001-000042",
                      "status": "issued",
                      "basis": "single",
                      "decision": "accept_standard",
                      "currency_code": "GBP",
                      "total_premium_monthly_pence": 1245,
                      "policy_fee_pence": 0,
                      "bundle_discount_pence": 0,
                      "issued_at": "2026-10-12T10:19:42+01:00",
                      "expires_at": "2026-11-11T10:19:42+00:00",
                      "accepted_at": null,
                      "superseded_by_id": null,
                      "assumptions": [],
                      "components": [
                        {
                          "id": "0199a3c2-7c01-7b88-8a0f-8d9eafb0c1d8",
                          "display_id": "qco_0199a3c2-7c01-7b88-8a0f-8d9eafb0c1d8",
                          "cover_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                          "cover_type": "life",
                          "component_index": 0,
                          "sum_assured_pence": 25000000,
                          "term_years": 25,
                          "decision": "accept_standard",
                          "rating_pct": 100,
                          "premium_monthly_pence": 1245,
                          "premium_annual_pence": 14940,
                          "exclusions": [],
                          "reasons": [],
                          "lives": [],
                          "member_count": null,
                          "title": "Life"
                        }
                      ],
                      "premium_illustration": null
                    },
                    "executions": [
                      {
                        "id": "0199a3c2-7c02-7c99-9b10-9eafb0c1d2e9",
                        "display_id": "exe_0199a3c2-7c02-7c99-9b10-9eafb0c1d2e9",
                        "cover_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                        "mode": "live",
                        "decision": "accept_standard",
                        "rating_pct": 100,
                        "exclusions": [],
                        "premium_monthly_pence": 1245,
                        "premium_annual_pence": 14940,
                        "rate_per_mille": "0.498",
                        "decline_reasons": [],
                        "referral_reasons": [],
                        "executed_at": "2026-10-12T10:19:42+01:00",
                        "trace": []
                      }
                    ]
                  }
                }
              }
            }
          },
          "200": {
            "description": "The application already existed (an idempotent retry, or `application_id`). This is it, with its quote (and its `share_token` only for a server-only application).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResult"
                },
                "example": {
                  "data": {
                    "application": {
                      "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "status": "quoted",
                      "idempotency_key": "quote-0001",
                      "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                      "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                      "customer": {
                        "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                        "title": "Ms",
                        "first_name": "Ada",
                        "last_name": "Lovelace",
                        "email": "ada@example.com",
                        "phone_number": "+447700900123",
                        "dob": "1988-04-12",
                        "postal_code": "SW1A 2AA",
                        "address_line1": "10 Example Street",
                        "address_line2": null,
                        "city": "London",
                        "country": "United Kingdom"
                      },
                      "joint_customer": null,
                      "risk_factors": {
                        "uk_resident": "yes",
                        "smoker": false
                      },
                      "cover_amount_pence": 25000000,
                      "term_years": 25,
                      "policy_id": null,
                      "abandoned_reason": null,
                      "presentation": {
                        "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "slug": "standard",
                        "name": "Standard",
                        "template_key": "standard",
                        "is_default": true,
                        "stages": [
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                            "key": "details",
                            "position": 1,
                            "stage_type": "personal_details",
                            "title": "Your details",
                            "cta_label": null,
                            "config": {
                              "fields": [
                                "first_name",
                                "last_name",
                                "email",
                                "phone",
                                "dob",
                                "address"
                              ]
                            },
                            "consent_notice": "We'll use these details to give you your quote and set up your policy."
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                            "key": "cover",
                            "position": 2,
                            "stage_type": "cover_capture",
                            "title": "Cover",
                            "cta_label": null,
                            "config": {}
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                            "key": "health_questions",
                            "position": 3,
                            "stage_type": "questions",
                            "title": "Health questions",
                            "cta_label": null,
                            "config": {
                              "all_remaining": true
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                            "key": "quote",
                            "position": 4,
                            "stage_type": "quote",
                            "title": "Your quote",
                            "cta_label": "Buy your policy",
                            "config": {
                              "label": "final"
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                            "key": "payment",
                            "position": 5,
                            "stage_type": "payment",
                            "title": "Payment",
                            "cta_label": null,
                            "config": {}
                          }
                        ]
                      },
                      "inline_bacs_mandate": false,
                      "direct_debit_first": false,
                      "stripe_test_mode": false,
                      "market_quotes": null,
                      "marketing_answered": false,
                      "created_at": "2026-10-12T10:15:00+01:00",
                      "updated_at": "2026-10-12T10:19:42+01:00",
                      "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                    },
                    "quote": {
                      "id": "0199a3c2-7c00-7a77-9f9e-7c8d9eafb0c7",
                      "display_id": "quo_0199a3c2-7c00-7a77-9f9e-7c8d9eafb0c7",
                      "reference": "QT-AB-P001-000042",
                      "status": "issued",
                      "basis": "single",
                      "decision": "accept_standard",
                      "currency_code": "GBP",
                      "total_premium_monthly_pence": 1245,
                      "policy_fee_pence": 0,
                      "bundle_discount_pence": 0,
                      "issued_at": "2026-10-12T10:19:42+01:00",
                      "expires_at": "2026-11-11T10:19:42+00:00",
                      "accepted_at": null,
                      "superseded_by_id": null,
                      "assumptions": [],
                      "components": [
                        {
                          "id": "0199a3c2-7c01-7b88-8a0f-8d9eafb0c1d8",
                          "display_id": "qco_0199a3c2-7c01-7b88-8a0f-8d9eafb0c1d8",
                          "cover_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                          "cover_type": "life",
                          "component_index": 0,
                          "sum_assured_pence": 25000000,
                          "term_years": 25,
                          "decision": "accept_standard",
                          "rating_pct": 100,
                          "premium_monthly_pence": 1245,
                          "premium_annual_pence": 14940,
                          "exclusions": [],
                          "reasons": [],
                          "lives": [],
                          "member_count": null,
                          "title": "Life"
                        }
                      ],
                      "premium_illustration": null
                    },
                    "executions": [
                      {
                        "id": "0199a3c2-7c02-7c99-9b10-9eafb0c1d2e9",
                        "display_id": "exe_0199a3c2-7c02-7c99-9b10-9eafb0c1d2e9",
                        "cover_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                        "mode": "live",
                        "decision": "accept_standard",
                        "rating_pct": 100,
                        "exclusions": [],
                        "premium_monthly_pence": 1245,
                        "premium_annual_pence": 14940,
                        "rate_per_mille": "0.498",
                        "decline_reasons": [],
                        "referral_reasons": [],
                        "executed_at": "2026-10-12T10:19:42+01:00",
                        "trace": []
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "409": {
            "description": "- `idempotency_key_conflict`: the `Idempotency-Key` was used before with different inputs.\n- `idempotency_replay_unproven`: a browser application sent an `Idempotency-Key` that already made an application, without that application's `share_token` in `X-Share-Token`. Nothing changed. Send the `share_token`, or start again with a new key.\n- `customer_mismatch`: `application_id` names an application that belongs to a different customer.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "idempotency_key_conflict",
                    "message": "Idempotency-Key 'quote-0001' has already been used with different inputs"
                  }
                }
              }
            }
          },
          "422": {
            "description": "No quote was made. `fields` names what to change, where it can:\n\n- `validation_failed`: a required field is missing.\n- `customer_invalid`: the customer's details aren't valid (as `customer.email`).\n- `answers_invalid`: an answer doesn't fit its question (as `risk_factors.smoker`).\n- `components_invalid`: a component can't be read: it names no\n  cover (neither `cover_type` nor `cover_id`), or its\n  `sum_assured_pence` or `term_years` is missing or isn't a whole\n  number (as `components[0].term_years`).\n- `cover_not_in_product`: the product has no such cover.\n- `cover_out_of_envelope`: the amount, age or term is outside the cover's limits (the message says which).\n- `quote_failed`: pricing failed (the message says why).\n- `rate_unavailable`: the details are acceptable, but there's no price for them.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cover_out_of_envelope",
                    "message": "Life cover is available from age 18 to 65 at the start of the policy (they would be 70)."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quotes/{id}": {
      "get": {
        "operationId": "getQuote",
        "tags": [
          "Quotes and applications"
        ],
        "summary": "Get a quote",
        "description": "A quote, with its application. Once the policy is set up, `policy`\nis there too, with the customer's links to their documents.\n\nThe application's `share_token` is only included for a server-only\napplication (or a token handed out for this one application).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "The quote and its application.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "application",
                        "quote"
                      ],
                      "properties": {
                        "application": {
                          "$ref": "#/components/schemas/Application"
                        },
                        "quote": {
                          "$ref": "#/components/schemas/Quote"
                        },
                        "policy": {
                          "$ref": "#/components/schemas/Policy"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "application": {
                      "id": "0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "display_id": "app_0199a3c2-7a00-7e55-9d7c-5a6b7c8d9ea5",
                      "status": "quoted",
                      "idempotency_key": "quote-0001",
                      "product_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f07",
                      "journey_id": "0199a3c2-6a10-7c2e-8d41-5b7f0e9c3a21",
                      "customer": {
                        "id": "0199a3c2-7b00-7f66-8e8d-6b7c8d9eafb6",
                        "title": "Ms",
                        "first_name": "Ada",
                        "last_name": "Lovelace",
                        "email": "ada@example.com",
                        "phone_number": "+447700900123",
                        "dob": "1988-04-12",
                        "postal_code": "SW1A 2AA",
                        "address_line1": "10 Example Street",
                        "address_line2": null,
                        "city": "London",
                        "country": "United Kingdom"
                      },
                      "joint_customer": null,
                      "risk_factors": {
                        "uk_resident": "yes",
                        "smoker": false
                      },
                      "cover_amount_pence": 25000000,
                      "term_years": 25,
                      "policy_id": null,
                      "abandoned_reason": null,
                      "presentation": {
                        "id": "0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "display_id": "prs_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94",
                        "slug": "standard",
                        "name": "Standard",
                        "template_key": "standard",
                        "is_default": true,
                        "stages": [
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_1",
                            "key": "details",
                            "position": 1,
                            "stage_type": "personal_details",
                            "title": "Your details",
                            "cta_label": null,
                            "config": {
                              "fields": [
                                "first_name",
                                "last_name",
                                "email",
                                "phone",
                                "dob",
                                "address"
                              ]
                            },
                            "consent_notice": "We'll use these details to give you your quote and set up your policy."
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_2",
                            "key": "cover",
                            "position": 2,
                            "stage_type": "cover_capture",
                            "title": "Cover",
                            "cta_label": null,
                            "config": {}
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_3",
                            "key": "health_questions",
                            "position": 3,
                            "stage_type": "questions",
                            "title": "Health questions",
                            "cta_label": null,
                            "config": {
                              "all_remaining": true
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_4",
                            "key": "quote",
                            "position": 4,
                            "stage_type": "quote",
                            "title": "Your quote",
                            "cta_label": "Buy your policy",
                            "config": {
                              "label": "final"
                            }
                          },
                          {
                            "id": "stg_0199a3c2-6c00-7d44-8c6b-4f5a6b7c8d94_5",
                            "key": "payment",
                            "position": 5,
                            "stage_type": "payment",
                            "title": "Payment",
                            "cta_label": null,
                            "config": {}
                          }
                        ]
                      },
                      "inline_bacs_mandate": false,
                      "direct_debit_first": false,
                      "stripe_test_mode": false,
                      "market_quotes": null,
                      "marketing_answered": false,
                      "created_at": "2026-10-12T10:15:00+01:00",
                      "updated_at": "2026-10-12T10:19:42+01:00",
                      "share_token": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
                    },
                    "quote": {
                      "id": "0199a3c2-7c00-7a77-9f9e-7c8d9eafb0c7",
                      "display_id": "quo_0199a3c2-7c00-7a77-9f9e-7c8d9eafb0c7",
                      "reference": "QT-AB-P001-000042",
                      "status": "issued",
                      "basis": "single",
                      "decision": "accept_standard",
                      "currency_code": "GBP",
                      "total_premium_monthly_pence": 1245,
                      "policy_fee_pence": 0,
                      "bundle_discount_pence": 0,
                      "issued_at": "2026-10-12T10:19:42+01:00",
                      "expires_at": "2026-11-11T10:19:42+00:00",
                      "accepted_at": null,
                      "superseded_by_id": null,
                      "assumptions": [],
                      "components": [
                        {
                          "id": "0199a3c2-7c01-7b88-8a0f-8d9eafb0c1d8",
                          "display_id": "qco_0199a3c2-7c01-7b88-8a0f-8d9eafb0c1d8",
                          "cover_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                          "cover_type": "life",
                          "component_index": 0,
                          "sum_assured_pence": 25000000,
                          "term_years": 25,
                          "decision": "accept_standard",
                          "rating_pct": 100,
                          "premium_monthly_pence": 1245,
                          "premium_annual_pence": 14940,
                          "exclusions": [],
                          "reasons": [],
                          "lives": [],
                          "member_count": null,
                          "title": "Life"
                        }
                      ],
                      "premium_illustration": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          }
        }
      }
    },
    "/api/v1/quotes/{id}/before_you_buy": {
      "get": {
        "operationId": "getBeforeYouBuy",
        "tags": [
          "Checkout"
        ],
        "summary": "What to show before they buy",
        "description": "What the customer must see before they can buy, under the rules your\nfirm has switched on: the product's demands and needs statement, its\nkey documents, their cancellation rights and a read-back of what\nthey're buying. Only the steps this sale still owes are included.\n\nWhen `show` is `true`, show these to the customer and, when they say\nyes, call [Confirm they've read it](/developers/api/reference/checkout#confirmBeforeYouBuy).\nWhen it's `false`, there's nothing to show, so go straight on.\n\nWhen `sellable` is `false`, the product can't be bought on a form\n(the demands and needs rule is on but the product has no statement). Offer the customer a conversation with your team instead.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "The steps still owed, with what to show for each.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/BeforeYouBuy"
                    }
                  }
                },
                "example": {
                  "data": {
                    "show": true,
                    "steps": [
                      "demands_and_needs",
                      "key_documents_before_bind",
                      "cancellation_rights_before_bind",
                      "confirm_before_purchase"
                    ],
                    "sellable": true,
                    "demands_and_needs": "This policy meets the demands and needs of someone who wants to leave a lump sum to their family if they die during the term.",
                    "key_documents": [
                      {
                        "document_id": "0199a3c2-7e00-7ebb-9d3c-b0c1d2e3f40b",
                        "version_id": "0199a3c2-7e01-7fcc-8e4d-c1d2e3f4051c",
                        "kind": "ipid",
                        "name": "Insurance product information document",
                        "url": "https://subcontext.com/documents/0199a3c2-7e01-7fcc-8e4d-c1d2e3f4051c"
                      }
                    ],
                    "cancellation": {
                      "days": 30,
                      "statement": "You can cancel within 30 days of the start date and get back everything you've paid."
                    },
                    "confirmation": {
                      "intro": "Before we set up your policy:",
                      "points": [
                        "Level Term Life.",
                        "Life cover of £250,000.00 for 25 years.",
                        "£12.45 a month.",
                        "Starting today, 12 October 2026."
                      ],
                      "question": "Are you happy for us to set this up?"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          }
        }
      }
    },
    "/api/v1/quotes/{id}/confirm": {
      "post": {
        "operationId": "confirmBeforeYouBuy",
        "tags": [
          "Checkout"
        ],
        "summary": "Confirm they've read it",
        "description": "The customer said yes on the \"before you buy\" screen. Records each\nstep it showed them (the statement confirmed, the documents and\ncancellation rights given, the read-back agreed), so setting up the\npolicy finds nothing owed. There's nothing to send. The record is made from what [What to show before they buy](/developers/api/reference/checkout#getBeforeYouBuy)\nshows.\n\n`owed` lists anything still owed afterwards (normally nothing).\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "Recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "owed"
                      ],
                      "properties": {
                        "owed": {
                          "type": "array",
                          "description": "Steps still owed, normally none.",
                          "items": {
                            "$ref": "#/components/schemas/SaleStep"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "owed": []
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "409": {
            "$ref": "#/components/responses/QuoteNotBindable"
          },
          "422": {
            "description": "`not_sellable`: the product can't be bought on a form. Offer a conversation instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_sellable",
                    "message": "This product needs a conversation with us before you buy."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quotes/{id}/direct_debit_details": {
      "post": {
        "operationId": "saveDirectDebitDetails",
        "tags": [
          "Checkout"
        ],
        "summary": "Save Direct Debit details",
        "description": "The customer's bank details for their monthly premiums. They're\nchecked (sort code and account number together) and stored\nencrypted. Sending them again replaces them.\n\nUse this when the application's `inline_bacs_mandate` is `false`.\nWhen it's `true`, the customer sets up the Direct Debit on Stripe's\nown form instead (see [Start a Direct Debit mandate](/developers/api/reference/checkout#createBacsSetupIntent)).\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "direct_debit"
                ],
                "properties": {
                  "direct_debit": {
                    "type": "object",
                    "required": [
                      "account_holder_name",
                      "sort_code",
                      "account_number"
                    ],
                    "properties": {
                      "account_holder_name": {
                        "type": "string",
                        "description": "The name on the account."
                      },
                      "sort_code": {
                        "type": "string",
                        "description": "Six digits, with or without dashes."
                      },
                      "account_number": {
                        "type": "string",
                        "description": "Eight digits."
                      },
                      "address_line1": {
                        "type": "string",
                        "description": "The account holder's address."
                      },
                      "address_line2": {
                        "type": "string"
                      },
                      "address_city": {
                        "type": "string"
                      },
                      "address_postal_code": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "example": {
                "direct_debit": {
                  "account_holder_name": "Ada Lovelace",
                  "sort_code": "40-47-84",
                  "account_number": "70872490",
                  "address_line1": "10 Example Street",
                  "address_city": "London",
                  "address_postal_code": "SW1A 2AA"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The details are saved.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "description": "The Direct Debit details, as saved.",
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "account_holder_name",
                        "sort_code",
                        "account_number_last4"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "account_holder_name": {
                          "type": "string"
                        },
                        "sort_code": {
                          "type": "string",
                          "description": "The sort code, as `40-47-84`."
                        },
                        "account_number_last4": {
                          "type": "string",
                          "description": "The last four digits of the account number, as `2490`."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-7f00-70dd-9f5e-d2e3f405162d",
                    "account_holder_name": "Ada Lovelace",
                    "sort_code": "40-47-84",
                    "account_number_last4": "2490"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "409": {
            "$ref": "#/components/responses/QuoteNotBindable"
          },
          "422": {
            "description": "- `direct_debit_invalid`: the details don't pass the checks (`fields` names each, as `direct_debit.sort_code`).\n- `validation_failed`: `direct_debit` is missing.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "direct_debit_invalid",
                    "message": "Sort code must be 6 digits",
                    "fields": {
                      "direct_debit.sort_code": "must be 6 digits"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quotes/{id}/bacs_setup_intent": {
      "post": {
        "operationId": "createBacsSetupIntent",
        "tags": [
          "Checkout"
        ],
        "summary": "Start a Direct Debit mandate",
        "description": "When the application's `inline_bacs_mandate` is `true`, starts a Stripe Checkout session in which the customer sets up their Direct\nDebit on Stripe's own form. Mount it with Stripe.js\n(`initEmbeddedCheckout` with the `client_secret`, your\n`publishable_key` and, when it isn't `null`, `stripe_account`).\nWhen the customer finishes, call [Record the Direct Debit mandate](/developers/api/reference/checkout#recordBacsMandate)\nwith the session's id.\n\nThe application needs a customer first.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "201": {
            "description": "The session, and the keys to mount it with.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "session",
                        "publishable_key",
                        "stripe_account"
                      ],
                      "properties": {
                        "session": {
                          "type": "object",
                          "additionalProperties": false,
                          "required": [
                            "id",
                            "client_secret"
                          ],
                          "properties": {
                            "id": {
                              "type": "string",
                              "description": "The Stripe Checkout session's id."
                            },
                            "client_secret": {
                              "type": "string",
                              "description": "What Stripe.js mounts the form with."
                            }
                          }
                        },
                        "publishable_key": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The Stripe publishable key for this product's payments."
                        },
                        "stripe_account": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Your firm's connected Stripe account, or `null` when payments go through Subcontext's own account."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "session": {
                      "id": "cs_live_a1B2c3D4",
                      "client_secret": "cs_live_a1B2c3D4_secret_e5F6"
                    },
                    "publishable_key": "pk_live_51Example",
                    "stripe_account": "acct_1Example"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "409": {
            "$ref": "#/components/responses/QuoteNotBindable"
          },
          "422": {
            "description": "- `customer_missing`: the application has no customer yet. Save their details first.\n- `bacs_setup_failed`: Stripe refused (the message says why).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "customer_missing",
                    "message": "The application has no customer yet: save their details before setting up the Direct Debit."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quotes/{id}/bacs_mandate": {
      "post": {
        "operationId": "recordBacsMandate",
        "tags": [
          "Checkout"
        ],
        "summary": "Record the Direct Debit mandate",
        "description": "After the customer finishes Stripe's Direct Debit form, send the session's id. Subcontext checks with Stripe that the mandate is set\nup, and keeps it for the policy's premiums.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "session_id"
                ],
                "properties": {
                  "session_id": {
                    "type": "string",
                    "description": "The Stripe Checkout session's id, from [Start a Direct Debit mandate](/developers/api/reference/checkout#createBacsSetupIntent)."
                  }
                }
              },
              "example": {
                "session_id": "cs_live_a1B2c3D4"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The mandate is recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "description": "The mandate, as recorded.",
                      "additionalProperties": false,
                      "required": [
                        "mandate_id",
                        "account_number_last4"
                      ],
                      "properties": {
                        "mandate_id": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Stripe's id for the mandate."
                        },
                        "account_number_last4": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The last four digits of the account number."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "mandate_id": "mandate_1Example",
                    "account_number_last4": "2490"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "409": {
            "$ref": "#/components/responses/QuoteNotBindable"
          },
          "422": {
            "description": "- `validation_failed`: `session_id` is missing.\n- `bacs_mandate_unconfirmed`: Stripe doesn't have the mandate set up yet (the customer hasn't finished, or the session isn't this one).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "bacs_mandate_unconfirmed",
                    "message": "the Direct Debit mandate is not confirmed yet"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quotes/{id}/payment_intent": {
      "post": {
        "operationId": "createPaymentIntent",
        "tags": [
          "Checkout"
        ],
        "summary": "Take the first premium by card",
        "description": "Creates the Stripe PaymentIntent for the first month's premium, and\ngives you the keys to mount Stripe's Payment Element with. When the\ncustomer has paid, call [Set up the policy](/developers/api/reference/checkout#bindQuote)\nwith the intent's id. Asking again for the same quote gives back the same intent, so the customer isn't charged twice.\n\nNot for a product whose first premium is taken by Direct Debit\n(the application's `direct_debit_first` is `true`). Set up the policy straight after the Direct Debit instead.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "201": {
            "description": "The PaymentIntent and the keys to mount it with.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "payment_intent",
                        "publishable_key",
                        "stripe_account"
                      ],
                      "properties": {
                        "payment_intent": {
                          "type": "object",
                          "additionalProperties": false,
                          "required": [
                            "id",
                            "client_secret",
                            "status",
                            "amount_pence",
                            "currency"
                          ],
                          "properties": {
                            "id": {
                              "type": "string",
                              "description": "The PaymentIntent's id. Send it to [Set up the policy](/developers/api/reference/checkout#bindQuote)."
                            },
                            "client_secret": {
                              "type": "string",
                              "description": "What Stripe.js mounts the Payment Element with."
                            },
                            "status": {
                              "type": "string",
                              "description": "Stripe's status for it, such as `requires_payment_method`."
                            },
                            "amount_pence": {
                              "type": "integer",
                              "description": "The first premium, in whole pence."
                            },
                            "currency": {
                              "type": "string",
                              "description": "The currency (ISO 4217), such as `GBP`."
                            }
                          }
                        },
                        "publishable_key": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The Stripe publishable key for this product's payments."
                        },
                        "stripe_account": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Your firm's connected Stripe account, or `null` when payments go through Subcontext's own account."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "payment_intent": {
                      "id": "pi_3Example",
                      "client_secret": "pi_3Example_secret_x9Y8",
                      "status": "requires_payment_method",
                      "amount_pence": 1245,
                      "currency": "GBP"
                    },
                    "publishable_key": "pk_live_51Example",
                    "stripe_account": "acct_1Example"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "409": {
            "$ref": "#/components/responses/QuoteNotBindable"
          },
          "422": {
            "description": "- `direct_debit_first`: this product takes its first premium by Direct Debit, so there's no card payment.\n- `payment_intent_creation_failed`: Stripe refused (the message says why).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "direct_debit_first",
                    "message": "This product takes its first premium by Direct Debit: no card payment is needed."
                  }
                }
              }
            }
          },
          "503": {
            "description": "`payments_unavailable`: your firm's Stripe account can't take payments yet. Nothing is wrong with the request. Finish connecting your Stripe account in the dashboard (**Organisation**, **Payments**), then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "payments_unavailable",
                    "message": "This organisation's Stripe account can't take payments yet."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quotes/{id}/bind": {
      "post": {
        "operationId": "bindQuote",
        "tags": [
          "Checkout"
        ],
        "summary": "Set up the policy",
        "description": "Sets up (binds) the policy from the quote. Everything is checked\nfirst: the quote is still current, nothing is owed from\n[What to show before they buy](/developers/api/reference/checkout#getBeforeYouBuy),\nthe Direct Debit is in place, and the first premium was paid (send\nthe card payment's `payment_intent_id`, which is checked with Stripe;\na Direct-Debit-first product needs none).\n\nThe policy starts today. A server-only application may set another\nstart date (up to 90 days ahead) and its own `policy_number`. From a browser, both are ignored.\n\nCalling it again once the policy is set up gives back the same\npolicy, with `200 OK`, so it's safe to retry.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/QuoteId"
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_intent_id": {
                    "type": "string",
                    "description": "The card payment for the first premium, from [Take the first premium by card](/developers/api/reference/checkout#createPaymentIntent). Not needed for a Direct-Debit-first product."
                  },
                  "commencement_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Server-only applications only. The start date, `YYYY-MM-DD`, from today to 90 days ahead."
                  },
                  "policy_number": {
                    "type": "string",
                    "description": "Server-only applications only. Your own policy number, when your systems issue them."
                  }
                }
              },
              "example": {
                "payment_intent_id": "pi_3Example"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The policy is set up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-8000-71ee-8a6f-e3f405162738",
                    "display_id": "pol_0199a3c2-8000-71ee-8a6f-e3f405162738",
                    "policy_number": "POL-AB-P001-000042",
                    "basis": "single",
                    "joint_customer_name": null,
                    "currency_code": "GBP",
                    "commencement_date": "2026-10-12",
                    "total_premium_monthly_pence": 1245,
                    "overall_decision": "accept_standard",
                    "pas_sync_status": "pending",
                    "bound_at": "2026-10-12T10:31:07+01:00",
                    "cancelled_at": null,
                    "components": [
                      {
                        "id": "0199a3c2-8001-72ff-9b70-f405162738a9",
                        "display_id": "comp_0199a3c2-8001-72ff-9b70-f405162738a9",
                        "cover_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                        "cover_type": "life",
                        "component_index": 0,
                        "sum_assured_pence": 25000000,
                        "term_years": 25,
                        "premium_monthly_pence": 1245,
                        "decision": "accept_standard",
                        "rating_pct": 100,
                        "exclusions": [],
                        "lives": [],
                        "commencement_date": "2026-10-12",
                        "cancelled_at": null
                      }
                    ],
                    "cessions": [],
                    "first_premium_record": {
                      "id": "0199a3c2-8002-7300-8c81-05162738a9ba",
                      "display_id": "pay_0199a3c2-8002-7300-8c81-05162738a9ba",
                      "kind": "first_premium",
                      "amount_pence": 1245,
                      "currency_code": "GBP",
                      "status": "collected",
                      "source": "system_initiated",
                      "processor": "stripe",
                      "processor_reference": "pi_3Example",
                      "occurred_at": "2026-10-12T10:31:07+01:00"
                    },
                    "policy_hub_path": "https://www.example.com/policy/Ro3oicP01pB-RlxbOFd01A2f7fgMDCAe",
                    "schedule_path": "https://www.example.com/policy/Ro3oicP01pB-RlxbOFd01A2f7fgMDCAe/schedule",
                    "documents": [
                      {
                        "id": "0199a3c2-7e00-7ebb-9d3c-b0c1d2e3f40b",
                        "kind": "policy_wording",
                        "name": "Policy wording",
                        "path": "https://www.example.com/policy/Ro3oicP01pB-RlxbOFd01A2f7fgMDCAe/documents/0199a3c2-7e00-7ebb-9d3c-b0c1d2e3f40b"
                      }
                    ],
                    "first_collection_on": "2026-11-12",
                    "collection_day_of_month": 12,
                    "wrap_up": null
                  }
                }
              }
            }
          },
          "200": {
            "description": "The policy was already set up. This is it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyEnvelope"
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-8000-71ee-8a6f-e3f405162738",
                    "display_id": "pol_0199a3c2-8000-71ee-8a6f-e3f405162738",
                    "policy_number": "POL-AB-P001-000042",
                    "basis": "single",
                    "joint_customer_name": null,
                    "currency_code": "GBP",
                    "commencement_date": "2026-10-12",
                    "total_premium_monthly_pence": 1245,
                    "overall_decision": "accept_standard",
                    "pas_sync_status": "pending",
                    "bound_at": "2026-10-12T10:31:07+01:00",
                    "cancelled_at": null,
                    "components": [
                      {
                        "id": "0199a3c2-8001-72ff-9b70-f405162738a9",
                        "display_id": "comp_0199a3c2-8001-72ff-9b70-f405162738a9",
                        "cover_id": "0199a3c2-5d1e-7b4a-9c3f-2e8d4b6a1f08",
                        "cover_type": "life",
                        "component_index": 0,
                        "sum_assured_pence": 25000000,
                        "term_years": 25,
                        "premium_monthly_pence": 1245,
                        "decision": "accept_standard",
                        "rating_pct": 100,
                        "exclusions": [],
                        "lives": [],
                        "commencement_date": "2026-10-12",
                        "cancelled_at": null
                      }
                    ],
                    "cessions": [],
                    "first_premium_record": {
                      "id": "0199a3c2-8002-7300-8c81-05162738a9ba",
                      "display_id": "pay_0199a3c2-8002-7300-8c81-05162738a9ba",
                      "kind": "first_premium",
                      "amount_pence": 1245,
                      "currency_code": "GBP",
                      "status": "collected",
                      "source": "system_initiated",
                      "processor": "stripe",
                      "processor_reference": "pi_3Example",
                      "occurred_at": "2026-10-12T10:31:07+01:00"
                    },
                    "policy_hub_path": "https://www.example.com/policy/Ro3oicP01pB-RlxbOFd01A2f7fgMDCAe",
                    "schedule_path": "https://www.example.com/policy/Ro3oicP01pB-RlxbOFd01A2f7fgMDCAe/schedule",
                    "documents": [
                      {
                        "id": "0199a3c2-7e00-7ebb-9d3c-b0c1d2e3f40b",
                        "kind": "policy_wording",
                        "name": "Policy wording",
                        "path": "https://www.example.com/policy/Ro3oicP01pB-RlxbOFd01A2f7fgMDCAe/documents/0199a3c2-7e00-7ebb-9d3c-b0c1d2e3f40b"
                      }
                    ],
                    "first_collection_on": "2026-11-12",
                    "collection_day_of_month": 12,
                    "wrap_up": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "`payment_not_succeeded`: the card payment hasn't gone through yet (for example it needs the customer to finish a bank check). Wait for Stripe, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "payment_not_succeeded",
                    "message": "The payment hasn't completed (status: requires_action)."
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApplicationNotFound"
          },
          "409": {
            "description": "- `quote_expired`: the quote has expired. Quote again.\n- `quote_not_bindable`: the quote can't be bought any more (it was replaced, or another quote was bought).\n- `already_bound`: the application already has a different policy.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "quote_expired",
                    "message": "This quote expired on 2026-11-11."
                  }
                }
              }
            }
          },
          "422": {
            "description": "The policy wasn't set up:\n\n- `sale_steps_owed`: something from [What to show before they buy](/developers/api/reference/checkout#getBeforeYouBuy) is still owed. Show it, confirm, and try again.\n- `direct_debit_missing`: no Direct Debit yet.\n- `payment_missing`: no `payment_intent_id`, and the product needs a card payment.\n- `payment_unverified`: Stripe doesn't know that payment.\n- `payment_mismatch`: that payment wasn't for this quote, or not for its first premium.\n- `invalid_start_date`: `commencement_date` isn't a date between today and 90 days ahead.\n- `payment_flow_invalid`: the product's payment settings can't work together. Ask your administrator.\n- `treaty_breach` or `bind_failed`: the policy couldn't be issued (the message says why).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "sale_steps_owed",
                    "message": "Before the policy can be set up the customer still needs: confirm before purchase."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/customers/validate_phone": {
      "get": {
        "operationId": "validatePhone",
        "tags": [
          "Lookups"
        ],
        "summary": "Check a phone number",
        "description": "Checks a phone number, for live feedback as the customer types it.\nA quick format check runs first. Numbers that pass it are checked\nwith a phone validation service (UK numbers without a country code\nare taken as UK).\n\nIf the validation service can't be reached, the number is treated as\nvalid (`reason` is `lookup_unavailable`), so an outage doesn't stop a customer.\n\nPass `application_id` when you have one. The check then uses the\napplication's presentation settings (for example, whether a mobile\nthat's switched off counts as invalid).\n",
        "parameters": [
          {
            "name": "phone",
            "in": "query",
            "required": true,
            "description": "The number as typed.",
            "schema": {
              "type": "string"
            },
            "example": "07700 900123"
          },
          {
            "name": "application_id",
            "in": "query",
            "required": false,
            "description": "The application the number is for, if there is one yet. An\nunknown id is ignored, and so is one a browser application sends\nwithout the application's `share_token` in `X-Share-Token`.\n",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "Whether the number is valid.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "valid"
                      ],
                      "properties": {
                        "valid": {
                          "type": "boolean",
                          "description": "Whether to accept the number."
                        },
                        "normalised": {
                          "type": "string",
                          "description": "The number tidied up, when it's valid."
                        },
                        "reason": {
                          "type": "string",
                          "description": "Why it's invalid, or why it was accepted without a full check.",
                          "enum": [
                            "blank",
                            "format_invalid",
                            "too_short",
                            "too_long",
                            "invalid_number",
                            "lookup_unavailable",
                            "drama_number"
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "valid": true,
                    "normalised": "+447700900123"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/addresses/lookup": {
      "get": {
        "operationId": "lookUpAddresses",
        "tags": [
          "Lookups"
        ],
        "summary": "Find addresses at a postcode",
        "description": "The addresses at a UK postcode, for an address picker. `valid` is\n`true` when the postcode found at least one address, and `town` is\nits post town. An unknown postcode (or a lookup that couldn't be\nmade) gives no addresses.\n",
        "parameters": [
          {
            "name": "postcode",
            "in": "query",
            "required": true,
            "description": "The postcode, with or without its space.",
            "schema": {
              "type": "string"
            },
            "example": "SW1A 2AA"
          },
          {
            "name": "application_id",
            "in": "query",
            "required": false,
            "description": "The application the address is for, if there is one yet. An\nunknown id is ignored, and so is one a browser application sends\nwithout the application's `share_token` in `X-Share-Token`.\n",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/ShareToken"
          }
        ],
        "responses": {
          "200": {
            "description": "The addresses found.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "addresses",
                        "valid",
                        "town"
                      ],
                      "properties": {
                        "addresses": {
                          "type": "array",
                          "description": "The addresses, ready to fill in a customer's address.",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "address_line1",
                              "address_line2",
                              "city",
                              "postal_code",
                              "country"
                            ],
                            "properties": {
                              "address_line1": {
                                "type": "string"
                              },
                              "address_line2": {
                                "type": "string",
                                "description": "Further lines, joined with commas. Empty when there are none."
                              },
                              "city": {
                                "type": "string",
                                "description": "The post town."
                              },
                              "postal_code": {
                                "type": "string",
                                "description": "The postcode, formatted with its space."
                              },
                              "country": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "valid": {
                          "type": "boolean",
                          "description": "Whether the postcode found any addresses."
                        },
                        "town": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The post town, or `null` when nothing was found."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "addresses": [
                      {
                        "address_line1": "10 Example Street",
                        "address_line2": "",
                        "city": "London",
                        "postal_code": "SW1A 2AA",
                        "country": "United Kingdom"
                      },
                      {
                        "address_line1": "Flat 2",
                        "address_line2": "12 Example Street",
                        "city": "London",
                        "postal_code": "SW1A 2AA",
                        "country": "United Kingdom"
                      }
                    ],
                    "valid": true,
                    "town": "London"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/crm/ingests": {
      "post": {
        "operationId": "createIngest",
        "tags": [
          "CRM: leads"
        ],
        "summary": "Send a lead",
        "description": "Sends a lead: who the person is (`identity`), what you know about\nthem, and where they came from. Server-only applications.\n\nThe answer is `202 Accepted`. Subcontext has stored the lead, and works out who it's about and reads it in the background. Poll\n[What became of a lead](/developers/api/reference/crm-leads#getIngest)\n(the `Location` header has its address) to see how that went.\n\nThe body is open. `data` takes any JSON your system has, and Subcontext reads it. Values you want stored exactly as\ngiven go in `declared`. You need at least one of `data`, `text`,\n`declared` or `identity`.\n\n**Idempotency:** send an `Idempotency-Key` header (your own record's\nid is ideal). The same key again within 10 minutes gives back the\nfirst answer, with an `Idempotent-Replay: true` header. After that it still never makes a second lead (`duplicate` is `true`). The same\ncontent from the same source within 5 minutes is also treated as a\nretry.\n",
        "security": [
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "source"
                ],
                "properties": {
                  "source": {
                    "type": "string",
                    "pattern": "^[a-z0-9_.-]{1,64}$",
                    "description": "Your system's name, such as `my_website` or `hubspot_webhook`. Lower-case letters, digits, `_`, `.` and `-`, up to 64 characters. `leadform` is reserved."
                  },
                  "campaign": {
                    "type": "string",
                    "description": "The key of the campaign the lead is for (in the dashboard, under **CRM**, **Campaigns**). Without it, only your organisation-wide rules apply."
                  },
                  "identity": {
                    "type": "object",
                    "description": "Who the person is. Any of `email`, `phone`, `name`, `first_name`, `last_name`, `external_id` (their id in your system).",
                    "additionalProperties": true
                  },
                  "data": {
                    "type": "object",
                    "description": "Anything else you know, in any shape. Subcontext reads it.",
                    "additionalProperties": true
                  },
                  "text": {
                    "type": "string",
                    "description": "Free text about the lead (a message, notes), read the same way."
                  },
                  "declared": {
                    "type": "object",
                    "description": "Values stored exactly as you give them, by field key, never interpreted. Values must be plain (not nested objects).",
                    "additionalProperties": true
                  },
                  "consent": {
                    "type": "object",
                    "description": "What the person agreed to, as your form recorded it: for\nexample `{ \"service\": { \"email\": true }, \"marketing\": { \"email\": false }, \"method\": \"web_form\" }`.\n",
                    "additionalProperties": true
                  },
                  "context": {
                    "type": "object",
                    "description": "What you know about the person's visit, such as `source_url`, `referrer`, `utm_source` or `user_agent`.",
                    "additionalProperties": true
                  },
                  "provenance": {
                    "$ref": "#/components/schemas/ProvenanceInput"
                  },
                  "occurred_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the lead happened, if not now (ISO 8601)."
                  },
                  "source_reference": {
                    "type": "string",
                    "description": "Your own reference for this lead, shown back to you."
                  }
                }
              },
              "example": {
                "source": "my_website",
                "campaign": "spring-life-2026",
                "identity": {
                  "first_name": "Ada",
                  "last_name": "Lovelace",
                  "email": "ada@example.com",
                  "phone": "07700 900123"
                },
                "data": {
                  "cover_wanted": 250000,
                  "reason": "New mortgage"
                },
                "consent": {
                  "service": {
                    "email": true,
                    "phone": true
                  },
                  "method": "web_form"
                },
                "provenance": {
                  "page_url": "https://www.example.com/life?utm_source=newsletter&utm_campaign=spring"
                },
                "source_reference": "web-12345"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The lead is stored and processed in the background. Poll its address (in the `Location` header) for what became of it.\n",
            "headers": {
              "Location": {
                "description": "The ingest's address, to poll.",
                "schema": {
                  "type": "string"
                },
                "example": "/api/v1/crm/ingests/0199a3c2-8100-7411-9d92-162738a9bacb"
              },
              "Idempotent-Replay": {
                "description": "`true` when this is the stored answer to an earlier request with the same `Idempotency-Key`.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Ingest"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-8100-7411-9d92-162738a9bacb",
                    "status": "received",
                    "source": "my_website",
                    "source_reference": "web-12345",
                    "received_at": "2026-10-12T10:40:12+01:00",
                    "facts_written": 0,
                    "fields_proposed": 0,
                    "activities_written": 0,
                    "truncated": false,
                    "provenance": {
                      "v": 1,
                      "captured_at": "2026-10-12T09:40:12Z",
                      "surface": "api",
                      "page_url": "https://www.example.com/life?utm_source=newsletter&utm_campaign=spring",
                      "host": "www.example.com",
                      "path": "/life",
                      "utm": {
                        "source": "newsletter",
                        "campaign": "spring"
                      },
                      "in_iframe": false,
                      "channel": "my_website"
                    },
                    "explanation": "Accepted; working out who this is about.",
                    "duplicate": false
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "The campaign isn't taking leads (`campaign_paused` or\n`campaign_archived`). The lead itself may be fine. Send it again when the campaign is active.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "campaign_paused",
                    "message": "this campaign is not accepting leads"
                  }
                }
              }
            }
          },
          "422": {
            "description": "The lead can never be accepted as sent:\n\n- `unknown_campaign`: no campaign with that key in your organisation.\n- `validation_failed`: the message says what's wrong, for example a missing or malformed `source`, nothing to go on, or more than 256 KB (`fields` names the input, when it's one).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "validation_failed",
                    "message": "source is required and must look like 'hubspot_webhook'",
                    "fields": {
                      "source": "source is required and must look like 'hubspot_webhook'"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crm/ingests/{id}": {
      "get": {
        "operationId": "getIngest",
        "tags": [
          "CRM: leads"
        ],
        "summary": "What became of a lead",
        "description": "Where a lead you sent has got to: still being read, applied to a\ncontact (`contact_id`, which is also the lead's id), held by your\ncampaign's rules, or waiting for a person to decide who it's about.\n`explanation` says it in words. Server-only applications, and\nonly the application that sent it can see it.\n\nA lead is done when `status` is `applied`, `needs_review`, `held`,\n`failed` or `discarded`. Until then, poll every few seconds.\n",
        "security": [
          {
            "oauth2": [
              "read",
              "crm"
            ]
          },
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ingest's id, from [Send a lead](/developers/api/reference/crm-leads#createIngest).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The ingest.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Ingest"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-8100-7411-9d92-162738a9bacb",
                    "status": "applied",
                    "source": "my_website",
                    "source_reference": "web-12345",
                    "received_at": "2026-10-12T10:40:12+01:00",
                    "processed_at": "2026-10-12T10:40:15+01:00",
                    "contact_id": "0199a3c2-8200-7522-8ea3-2738a9bacbdc",
                    "facts_written": 3,
                    "fields_proposed": 0,
                    "activities_written": 0,
                    "truncated": false,
                    "explanation": "Applied to contact 0199a3c2-8200-7522-8ea3-2738a9bacbdc; 3 fact(s) recorded."
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/crm/leads": {
      "get": {
        "operationId": "listLeads",
        "tags": [
          "CRM: leads"
        ],
        "summary": "List your leads",
        "description": "The leads this application sent, and where each is now, oldest change first. A lead that changes comes round again, so this is a\nfeed of what has changed. Server-only applications.\n\nPage through with `cursor`, as every list in the API does. Pass each page's `next_cursor` to get the next, and keep the last one to ask\n\"what's changed since?\" next time. A page with fewer than `limit`\nleads is the last for now. To start from a time rather than the\nbeginning, send `updated_since` (and no `cursor`).\n\nFilter by `status` (one or more, comma separated) and `campaign_id`.\n",
        "security": [
          {
            "oauth2": [
              "read",
              "crm"
            ]
          },
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only leads with these outcomes, comma separated (for example\n`won,lost`): `open`, `won`, `lost`, `dormant`, `disqualified`,\n`duplicate`, `invalid`, `not_interested` or `ineligible`. Any other\nvalue is refused.\n",
            "schema": {
              "type": "string"
            },
            "example": "won"
          },
          {
            "name": "campaign_id",
            "in": "query",
            "required": false,
            "description": "Only leads for this campaign.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Start with the leads changed at or after this time (ISO 8601), instead of from the beginning. Ignored when you send `cursor`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many leads per page, 1 to 200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of leads.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The leads, oldest change first.",
                      "items": {
                        "$ref": "#/components/schemas/Lead"
                      }
                    },
                    "next_cursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "contact_id": "0199a3c2-8200-7522-8ea3-2738a9bacbdc",
                      "external_system_id": "CRM-88123",
                      "status": "won",
                      "terminal": true,
                      "stage": {
                        "key": "won",
                        "name": "Won",
                        "kind": "won",
                        "probability": 100
                      },
                      "stage_entered_at": "2026-10-14T16:02:11+01:00",
                      "owner_assigned": true,
                      "score": 71,
                      "campaign_id": "0199a3c2-8300-7633-9fb4-38a9bacbdced",
                      "first_touched_at": "2026-10-12T10:52:40+01:00",
                      "last_touched_at": "2026-10-14T16:02:11+01:00",
                      "created_at": "2026-10-12T10:40:15+01:00",
                      "updated_at": "2026-10-14T16:02:11+01:00"
                    }
                  ],
                  "next_cursor": "MjAyNi0xMC0xNFQxNTowMjoxMS4wMDAwMDBafDAxOTlhM2MyLTgyMDAtNzUyMi04ZWEzLTI3MzhhOWJhY2JkYw"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "`invalid_parameter`: `cursor` isn't one the API gave you, `updated_since` isn't an ISO 8601 time, or `status` has a value that isn't a lead status. `fields` names it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_parameter",
                    "message": "cursor isn't one this API gave you: pass a page's next_cursor as it came.",
                    "fields": {
                      "cursor": "isn't one this API gave you: pass a page's next_cursor as it came"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crm/leads/{id}": {
      "get": {
        "operationId": "getLead",
        "tags": [
          "CRM: leads"
        ],
        "summary": "Get a lead",
        "description": "Where one lead you sent is now: its stage, its outcome, whether\nsomeone owns it, and its score. Find it by the `contact_id` from\n[What became of a lead](/developers/api/reference/crm-leads#getIngest).\nServer-only applications, and only the leads this application sent.\n\nIt doesn't include the person's details, since you sent them.\n",
        "security": [
          {
            "oauth2": [
              "read",
              "crm"
            ]
          },
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The lead's `contact_id`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The lead.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Lead"
                    }
                  }
                },
                "example": {
                  "data": {
                    "contact_id": "0199a3c2-8200-7522-8ea3-2738a9bacbdc",
                    "external_system_id": "CRM-88123",
                    "status": "won",
                    "terminal": true,
                    "stage": {
                      "key": "won",
                      "name": "Won",
                      "kind": "won",
                      "probability": 100
                    },
                    "stage_entered_at": "2026-10-14T16:02:11+01:00",
                    "owner_assigned": true,
                    "score": 71,
                    "campaign_id": "0199a3c2-8300-7633-9fb4-38a9bacbdced",
                    "first_touched_at": "2026-10-12T10:52:40+01:00",
                    "last_touched_at": "2026-10-14T16:02:11+01:00",
                    "created_at": "2026-10-12T10:40:15+01:00",
                    "updated_at": "2026-10-14T16:02:11+01:00"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "There's no lead for that contact id that this application sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "No lead for that contact id."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crm/events": {
      "get": {
        "operationId": "listLeadEvents",
        "tags": [
          "CRM: leads"
        ],
        "summary": "List what happened to your leads",
        "description": "A feed of what has happened to the leads this application sent,\noldest first: stage changes, outcomes, owners assigned, messages and\ncalls. Server-only applications.\n\nEach event says what happened and to whom, but not what was said or written. Use it as a prompt to [get the lead](/developers/api/reference/crm-leads#getLead).\n\nTo keep up, pass the last page's `next_cursor` as `cursor`. Events\nare kept for your organisation's retention period, so poll at least\nthat often.\n",
        "security": [
          {
            "oauth2": [
              "read",
              "crm"
            ]
          },
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "Only this lead's events.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "event",
            "in": "query",
            "required": false,
            "description": "Only these kinds of event, comma separated (for example `lead.stage_changed,lead.status_changed`). A kind the feed doesn't record is refused.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many events per page, 1 to 500.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of events.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The events, oldest first.",
                      "items": {
                        "$ref": "#/components/schemas/LeadEvent"
                      }
                    },
                    "next_cursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "0199a3c2-8400-7744-8ac5-49bacbdcedfe",
                      "event": "lead.stage_changed",
                      "contact_id": "0199a3c2-8200-7522-8ea3-2738a9bacbdc",
                      "campaign_id": "0199a3c2-8300-7633-9fb4-38a9bacbdced",
                      "occurred_at": "2026-10-13T09:12:30+01:00",
                      "detail": {
                        "from": "new",
                        "to": "quoted"
                      }
                    },
                    {
                      "id": "0199a3c2-8401-7855-9bd6-5acbdcedfe0f",
                      "event": "lead.status_changed",
                      "contact_id": "0199a3c2-8200-7522-8ea3-2738a9bacbdc",
                      "campaign_id": "0199a3c2-8300-7633-9fb4-38a9bacbdced",
                      "occurred_at": "2026-10-14T16:02:11+01:00",
                      "detail": {
                        "from": "open",
                        "to": "won"
                      }
                    }
                  ],
                  "next_cursor": "MDE5OWEzYzItODQwMS03ODU1LTliZDYtNWFjYmRjZWRmZTBm"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "`invalid_parameter`: `event` has a kind of event the feed doesn't record, or `cursor` isn't one the API gave you. `fields` names it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_parameter",
                    "message": "event has \"lead.stage_change\", not an event this feed records.",
                    "fields": {
                      "event": "has \"lead.stage_change\", not an event this feed records"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crm/outcomes/reverse": {
      "post": {
        "operationId": "reverseOutcomeByEventId",
        "tags": [
          "CRM: outcomes"
        ],
        "summary": "Reverse an outcome by your event id",
        "description": "Undoes an outcome you sent in error, found by the `event_id` you\nsent it with. The record keeps both the outcome and its reversal,\nand reports stop counting it. To correct one, reverse it and send it\nagain with a new `event_id`. A sale that was cancelled is an outcome of its own, of type `cancelled`, rather than a reversal.\n\nServer-only applications. With only the `crm` scope, only\noutcomes for the leads this application sent.\n",
        "security": [
          {
            "oauth2": [
              "write",
              "outcomes"
            ]
          },
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "event_id"
                ],
                "properties": {
                  "event_id": {
                    "type": "string",
                    "description": "The `event_id` you sent the outcome with."
                  },
                  "note": {
                    "type": "string",
                    "description": "Why, for your team (up to 500 characters)."
                  }
                }
              },
              "example": {
                "event_id": "sale-77812",
                "note": "Recorded against the wrong customer."
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/OutcomeReversed"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/AlreadyReversed"
          }
        }
      }
    },
    "/api/v1/crm/outcomes/model": {
      "get": {
        "operationId": "getOutcomeModel",
        "tags": [
          "CRM: outcomes"
        ],
        "summary": "The outcomes you can send",
        "description": "Your organisation's outcome types (such as `quoted`, `sold` and\n`cancelled`), the values each takes (such as `annual_premium` and\n`commission`), and your products, so you know what to send. Your\norganisation can add its own in the dashboard.\n\nServer-only applications.\n",
        "security": [
          {
            "oauth2": [
              "read",
              "outcomes"
            ]
          },
          {
            "oauth2": [
              "write",
              "outcomes"
            ]
          },
          {
            "oauth2": [
              "read",
              "crm"
            ]
          },
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The outcome types, values and products.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "types",
                        "measures",
                        "products"
                      ],
                      "properties": {
                        "types": {
                          "type": "array",
                          "description": "The outcome types, each a `type` you can send.",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "key",
                              "label",
                              "repeatable",
                              "product",
                              "values"
                            ],
                            "properties": {
                              "key": {
                                "type": "string",
                                "description": "What to send as `type`."
                              },
                              "label": {
                                "type": "string"
                              },
                              "repeatable": {
                                "type": "boolean",
                                "description": "Whether a lead can have this outcome more than once."
                              },
                              "product": {
                                "type": "string",
                                "description": "Whether an outcome of this type names a `product`.",
                                "enum": [
                                  "none",
                                  "optional",
                                  "required"
                                ]
                              },
                              "values": {
                                "type": "array",
                                "description": "The values it takes.",
                                "items": {
                                  "type": "object",
                                  "additionalProperties": false,
                                  "required": [
                                    "key",
                                    "required",
                                    "calculated"
                                  ],
                                  "properties": {
                                    "key": {
                                      "type": "string",
                                      "description": "A measure's key, to use in `values`."
                                    },
                                    "required": {
                                      "type": "boolean",
                                      "description": "Whether you must send it."
                                    },
                                    "calculated": {
                                      "type": "boolean",
                                      "description": "Whether Subcontext works it out from the others (no need to send it)."
                                    }
                                  }
                                }
                              }
                            }
                          }
                        },
                        "measures": {
                          "type": "array",
                          "description": "The values outcomes can carry.",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "key",
                              "label",
                              "unit"
                            ],
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "unit": {
                                "type": "string",
                                "description": "`money` in whole pence (`24950` is £249.50), `percent` as a percentage (`22.5`), `count` as a whole number.",
                                "enum": [
                                  "money",
                                  "count",
                                  "percent"
                                ]
                              }
                            }
                          }
                        },
                        "products": {
                          "type": "array",
                          "description": "Your products, for `product` on an outcome.",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "key",
                              "name",
                              "aliases"
                            ],
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "aliases": {
                                "type": "array",
                                "description": "Other codes your systems use for it, which work too.",
                                "items": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "types": [
                      {
                        "key": "quoted",
                        "label": "Quoted",
                        "repeatable": false,
                        "product": "optional",
                        "values": [
                          {
                            "key": "monthly_premium",
                            "required": false,
                            "calculated": false
                          },
                          {
                            "key": "annual_premium",
                            "required": false,
                            "calculated": false
                          }
                        ]
                      },
                      {
                        "key": "sold",
                        "label": "Sold",
                        "repeatable": false,
                        "product": "optional",
                        "values": [
                          {
                            "key": "monthly_premium",
                            "required": false,
                            "calculated": false
                          },
                          {
                            "key": "annual_premium",
                            "required": false,
                            "calculated": false
                          },
                          {
                            "key": "commission",
                            "required": false,
                            "calculated": false
                          }
                        ]
                      },
                      {
                        "key": "cancelled",
                        "label": "Cancelled",
                        "repeatable": false,
                        "product": "optional",
                        "values": [
                          {
                            "key": "clawback",
                            "required": false,
                            "calculated": false
                          }
                        ]
                      }
                    ],
                    "measures": [
                      {
                        "key": "monthly_premium",
                        "label": "Monthly premium",
                        "unit": "money"
                      },
                      {
                        "key": "annual_premium",
                        "label": "Annual premium",
                        "unit": "money"
                      },
                      {
                        "key": "commission",
                        "label": "Commission",
                        "unit": "money"
                      },
                      {
                        "key": "clawback",
                        "label": "Clawback",
                        "unit": "money"
                      }
                    ],
                    "products": [
                      {
                        "key": "level-term",
                        "name": "Level Term Life",
                        "aliases": [
                          "LTL",
                          "LT01"
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/crm/outcomes/{id}/reverse": {
      "post": {
        "operationId": "reverseOutcome",
        "tags": [
          "CRM: outcomes"
        ],
        "summary": "Reverse an outcome",
        "description": "The same as [Reverse an outcome by your event id](/developers/api/reference/crm-outcomes#reverseOutcomeByEventId),\nfound by Subcontext's id for the outcome instead.\n",
        "security": [
          {
            "oauth2": [
              "write",
              "outcomes"
            ]
          },
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The outcome's `id`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "type": "string",
                    "description": "Why, for your team (up to 500 characters)."
                  }
                }
              },
              "example": {
                "note": "Duplicate of an earlier sale."
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/OutcomeReversed"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/AlreadyReversed"
          }
        }
      }
    },
    "/api/v1/crm/outcomes": {
      "get": {
        "operationId": "listOutcomes",
        "tags": [
          "CRM: outcomes"
        ],
        "summary": "List outcomes",
        "description": "The outcomes recorded, oldest first, reversals included. With only\nthe `crm` scope, only those for the leads this application sent.\nServer-only applications.\n\nPage through by passing the last page's `next_cursor` as `cursor`.\nFilter by lead (`contact_id`), deal (`deal_ref`) or `type`.\n",
        "security": [
          {
            "oauth2": [
              "read",
              "outcomes"
            ]
          },
          {
            "oauth2": [
              "write",
              "outcomes"
            ]
          },
          {
            "oauth2": [
              "read",
              "crm"
            ]
          },
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "Only this lead's outcomes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "deal_ref",
            "in": "query",
            "required": false,
            "description": "Only outcomes for this deal.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Only outcomes of this type (its key). A key that isn't one of your outcome types is refused.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many per page, 1 to 200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of outcomes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "next_cursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The outcomes, oldest first.",
                      "items": {
                        "$ref": "#/components/schemas/Outcome"
                      }
                    },
                    "next_cursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "0199a3c2-8500-7966-8ce7-6bdcedfe0f10",
                      "event_id": "sale-77812",
                      "type": "sold",
                      "contact_id": "0199a3c2-8200-7522-8ea3-2738a9bacbdc",
                      "occurred_at": "2026-10-20T14:00:00+01:00",
                      "source": "api",
                      "deal_ref": "DEAL-5521",
                      "product": "level-term",
                      "values": {
                        "annual_premium": 14940,
                        "commission": 26892
                      },
                      "missing_values": [],
                      "currency": "GBP",
                      "reversed": false,
                      "reversal_of": null
                    }
                  ],
                  "next_cursor": "MDE5OWEzYzItODUwMC03OTY2LThjZTctNmJkY2VkZmUwZjEw"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "`invalid_parameter`: `type` isn't one of your outcome types, or `cursor` isn't one the API gave you. `fields` names it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_parameter",
                    "message": "type isn't one of your outcome types.",
                    "fields": {
                      "type": "isn't one of your outcome types"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "recordOutcomes",
        "tags": [
          "CRM: outcomes"
        ],
        "summary": "Report outcomes",
        "description": "Reports what became of leads, with one outcome as the body or up to 500 as `{ \"outcomes\": [...] }`. Server-only applications.\n\nEach outcome names its lead by Subcontext's id (`lead.id`, the\n`contact_id` sent with every lead), your system's id for it\n(`lead.external_id`), or, if you set `lead.match_on_details`, its\nemail address or phone number. Each one gets its own result, in\norder:\n\n- `recorded`: matched to its lead and recorded.\n- `duplicate`: an outcome with this `event_id` was already recorded. Nothing changed, so it's safe to send again.\n- `held`: no single lead matched. It waits in your team's review queue to be matched by hand (`submission_id` names it).\n- `invalid`: it can never be recorded as sent (`error` says why).\n- `conflict`: it's valid, but clashes with an outcome the lead already has (`error` says which).\n\nMoney is in whole pence (`14940` is £149.40), as everywhere in the API. A money value that isn't a whole number of pence makes that outcome `invalid`. Percentages are percentages (`22.5`). With only\nthe `crm` scope, only the leads this application sent can match.\n",
        "security": [
          {
            "oauth2": [
              "write",
              "outcomes"
            ]
          },
          {
            "oauth2": [
              "write",
              "crm"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/OutcomeInput"
                  },
                  {
                    "type": "object",
                    "required": [
                      "outcomes"
                    ],
                    "properties": {
                      "outcomes": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 500,
                        "items": {
                          "$ref": "#/components/schemas/OutcomeInput"
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "outcomes": [
                  {
                    "event_id": "sale-77812",
                    "type": "sold",
                    "occurred_at": "2026-10-20T14:00:00+01:00",
                    "lead": {
                      "id": "0199a3c2-8200-7522-8ea3-2738a9bacbdc"
                    },
                    "deal_ref": "DEAL-5521",
                    "product": "LTL",
                    "values": {
                      "annual_premium": 14940,
                      "commission": 26892
                    }
                  },
                  {
                    "event_id": "sale-77813",
                    "type": "sold",
                    "occurred_at": "2026-10-20T15:30:00+01:00",
                    "lead": {
                      "external_id": "CRM-90211"
                    },
                    "values": {
                      "annual_premium": 21204
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A result for each outcome, in the order sent, and a count of each result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "counts",
                        "results"
                      ],
                      "properties": {
                        "counts": {
                          "type": "object",
                          "description": "How many outcomes got each result, such as `{ \"recorded\": 1, \"held\": 1 }`. Results with none are left out.",
                          "additionalProperties": {
                            "type": "integer"
                          },
                          "propertyNames": {
                            "enum": [
                              "recorded",
                              "duplicate",
                              "held",
                              "invalid",
                              "conflict"
                            ]
                          }
                        },
                        "results": {
                          "type": "array",
                          "description": "One for each outcome sent, in order.",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "status"
                            ],
                            "properties": {
                              "event_id": {
                                "type": "string",
                                "description": "The `event_id` you sent, if you sent one."
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "recorded",
                                  "duplicate",
                                  "held",
                                  "invalid",
                                  "conflict"
                                ]
                              },
                              "error": {
                                "type": "string",
                                "description": "Why it was held, refused or clashed."
                              },
                              "outcome": {
                                "$ref": "#/components/schemas/Outcome"
                              },
                              "submission_id": {
                                "type": "string",
                                "format": "uuid",
                                "description": "For a held outcome, its place in the review queue."
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "counts": {
                      "recorded": 1,
                      "held": 1
                    },
                    "results": [
                      {
                        "event_id": "sale-77812",
                        "status": "recorded",
                        "outcome": {
                          "id": "0199a3c2-8500-7966-8ce7-6bdcedfe0f10",
                          "event_id": "sale-77812",
                          "type": "sold",
                          "contact_id": "0199a3c2-8200-7522-8ea3-2738a9bacbdc",
                          "occurred_at": "2026-10-20T14:00:00+01:00",
                          "source": "api",
                          "deal_ref": "DEAL-5521",
                          "product": "level-term",
                          "values": {
                            "annual_premium": 14940,
                            "commission": 26892
                          },
                          "missing_values": [],
                          "currency": "GBP",
                          "reversed": false,
                          "reversal_of": null
                        }
                      },
                      {
                        "event_id": "sale-77813",
                        "status": "held",
                        "error": "no lead matches those identifiers",
                        "submission_id": "0199a3c2-8600-7a77-9df8-7cedfe0f1021"
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "`validation_failed`: send between 1 and 500 outcomes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "validation_failed",
                    "message": "Send between 1 and 500 outcomes.",
                    "fields": {
                      "outcomes": "Send between 1 and 500 outcomes."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/programme_memberships/{external_ref}/events": {
      "post": {
        "operationId": "recordMembershipEvents",
        "tags": [
          "Loyalty"
        ],
        "summary": "Send points and tiers",
        "description": "Sends what a member has earned: points awarded or adjusted, and the\ntier your programme says they're on. Members earn once their\nenrolment is confirmed. Until then this answers `409`. Either all of a batch is recorded or none of it is, so you can send a failed delivery again. Each event needs its own `idempotency_key`, and one already recorded is skipped (`replayed` is `true`).\n\nServer-only applications, with the `write` scope.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MembershipRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "events"
                ],
                "properties": {
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "idempotency_key",
                        "entry_type"
                      ],
                      "properties": {
                        "idempotency_key": {
                          "type": "string",
                          "description": "Unique to this event in your system."
                        },
                        "entry_type": {
                          "type": "string",
                          "enum": [
                            "points_awarded",
                            "points_adjusted",
                            "tier_asserted"
                          ],
                          "description": "Points earned, a correction to points (can be negative), or the tier the member is on."
                        },
                        "points": {
                          "type": "integer",
                          "description": "For points events, how many."
                        },
                        "tier_key": {
                          "type": "string",
                          "description": "For `tier_asserted`, the tier's key (as set up on the programme)."
                        },
                        "occurred_at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When it happened (ISO 8601). Now if left out."
                        },
                        "payload": {
                          "type": "object",
                          "description": "Anything else to keep with the event, such as the activity that earned the points.",
                          "additionalProperties": true
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "events": [
                  {
                    "idempotency_key": "vit-evt-55120",
                    "entry_type": "points_awarded",
                    "points": 500,
                    "occurred_at": "2026-10-11T07:30:00Z",
                    "payload": {
                      "activity": "weekly_steps"
                    }
                  },
                  {
                    "idempotency_key": "vit-evt-55121",
                    "entry_type": "tier_asserted",
                    "tier_key": "silver"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The batch is recorded. The membership shows its new points and tier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "events",
                        "membership"
                      ],
                      "properties": {
                        "events": {
                          "type": "array",
                          "description": "One for each event, in order.",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "entry_type",
                              "points",
                              "tier_key",
                              "replayed"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "format": "uuid"
                              },
                              "entry_type": {
                                "type": "string",
                                "enum": [
                                  "points_awarded",
                                  "points_adjusted",
                                  "tier_asserted"
                                ]
                              },
                              "points": {
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "tier_key": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "replayed": {
                                "type": "boolean",
                                "description": "`true` when this event was already recorded."
                              }
                            }
                          }
                        },
                        "membership": {
                          "$ref": "#/components/schemas/Membership"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "events": [
                      {
                        "id": "0199a3c2-8700-7b88-8e09-8dfe0f102132",
                        "entry_type": "points_awarded",
                        "points": 500,
                        "tier_key": null,
                        "replayed": false
                      },
                      {
                        "id": "0199a3c2-8701-7c99-9f1a-9e0f10213243",
                        "entry_type": "tier_asserted",
                        "points": 0,
                        "tier_key": "silver",
                        "replayed": false
                      }
                    ],
                    "membership": {
                      "id": "0199a3c2-8800-7daa-8a2b-af1021324354",
                      "programme_slug": "rewards",
                      "programme_name": "Rewards",
                      "policy_number": "POL-AB-P001-000042",
                      "status": "active",
                      "external_member_ref": "VIT-1001",
                      "current_tier_key": "silver",
                      "cycle_points": 2400,
                      "cycle_started_on": "2026-01-01",
                      "cycle_ends_on": "2026-12-31"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Nothing was recorded:\n\n- `membership_pending`: the enrolment isn't confirmed yet. Confirm it with [Update a membership](/developers/api/reference/loyalty#updateMembership) first.\n- `membership_cancelled`: the membership is cancelled and earns nothing more.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "membership_cancelled",
                    "message": "this membership is cancelled and can't be changed"
                  }
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed`: one of the events isn't valid (an unknown\n`entry_type`, a missing `idempotency_key` or tier, a time that\nisn't ISO 8601), or `events` is missing. `fields` names it, as\n`events[1].entry_type`. Nothing in the batch was recorded.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "validation_failed",
                    "message": "events[1].idempotency_key is required on every event",
                    "fields": {
                      "events[1].idempotency_key": "is required on every event"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/programme_memberships/{external_ref}": {
      "get": {
        "operationId": "getMembership",
        "tags": [
          "Loyalty"
        ],
        "summary": "Get a membership",
        "description": "A membership as it is now: its status, your reference, its tier and\nthe points earned this cycle. Before you've confirmed the enrolment,\nfind it by Subcontext's membership id. After that, find it by your reference.\n\nServer-only applications.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/MembershipRef"
          }
        ],
        "responses": {
          "200": {
            "description": "The membership.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Membership"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-8800-7daa-8a2b-af1021324354",
                    "programme_slug": "rewards",
                    "programme_name": "Rewards",
                    "policy_number": "POL-AB-P001-000042",
                    "status": "pending",
                    "external_member_ref": null,
                    "current_tier_key": "bronze",
                    "cycle_points": 0,
                    "cycle_started_on": "2026-10-12",
                    "cycle_ends_on": "2027-10-12"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "operationId": "updateMembership",
        "tags": [
          "Loyalty"
        ],
        "summary": "Update a membership",
        "description": "Confirms an enrolment or changes a membership's status.\n\nWhen a policyholder joins, the membership starts `pending`, and you\nfind it by Subcontext's membership id. Confirm it by sending your\nown member reference (`external_member_ref`) and `status: active`.\nFrom then on, use your reference in the address.\n\nLater, send `status` to suspend (`suspended`), reinstate (`active`)\nor end (`cancelled`) it. A cancelled membership can't be changed.\n\nSending `external_member_ref` on its own, with no `status`, records\nit as the member's reference while the membership is `pending`. Once a reference is confirmed it's fixed. Sending the same one again is harmless, and a different one is refused\n(`409 external_member_ref_mismatch`), as when confirming. Only your firm's own team can correct a confirmed reference, in the dashboard.\n\nServer-only applications, with the `write` scope.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MembershipRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MembershipInput"
              },
              "example": {
                "status": "active",
                "external_member_ref": "VIT-1001"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/MembershipUpdated"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/MembershipConflict"
          },
          "422": {
            "$ref": "#/components/responses/MembershipInvalid"
          }
        }
      },
      "put": {
        "operationId": "replaceMembership",
        "tags": [
          "Loyalty"
        ],
        "summary": "Update a membership (PUT)",
        "description": "The same as [Update a membership](/developers/api/reference/loyalty#updateMembership),\nfor systems that send `PUT`. It works as `PATCH` does. Only the fields you send change, and it doesn't replace the whole membership.\n",
        "security": [
          {
            "oauth2": [
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MembershipRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MembershipInput"
              },
              "example": {
                "status": "suspended"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/MembershipUpdated"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/MembershipConflict"
          },
          "422": {
            "$ref": "#/components/responses/MembershipInvalid"
          }
        }
      }
    },
    "/api/v1/outreach/streams/{id}": {
      "get": {
        "operationId": "getOutreachStream",
        "tags": [
          "Outreach"
        ],
        "summary": "Get an outreach stream",
        "description": "An outreach stream's settings and progress: how many people are in\nit, how many have been messaged, and how many replied, booked,\napplied and bought. Server-only applications.\n\nOutreach streams must be switched on for your organisation. If they aren't, every stream is `404`.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The stream's id (in the dashboard, in the stream's address).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The stream.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/OutreachStream"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "0199a3c2-8900-7ebb-9b3c-b02132435465",
                    "name": "Mortgage renewals, October",
                    "status": "active",
                    "archived_at": null,
                    "kind": "conversation",
                    "purpose": "first_party_marketing",
                    "goal": "bookings",
                    "channels": [
                      "whatsapp",
                      "email"
                    ],
                    "all_channels": false,
                    "follow_up_after_days": 3,
                    "auto_send": true,
                    "pace_per_hour": 40,
                    "message_mode": "drafted",
                    "from_name": null,
                    "reply_email_template_key": "plain",
                    "reply_email_template_id": null,
                    "date_column": null,
                    "date_field": null,
                    "offset_days": null,
                    "send_at_local_time": null,
                    "schedule": null,
                    "next_issue_at": null,
                    "skip_if_unchanged": null,
                    "issues_sent_count": null,
                    "subscribed_count": null,
                    "survey": null,
                    "survey_answered_count": null,
                    "awaiting_approval_count": 0,
                    "rows_count": 420,
                    "analysed_count": 418,
                    "skipped_count": 12,
                    "sent_count": 396,
                    "errored_count": 2,
                    "outcomes": {
                      "replied": 88,
                      "booked": 31,
                      "applications": 9,
                      "bound": 4
                    },
                    "total_cost_pence": 1454,
                    "cost_ceiling_pence": 3950,
                    "budget_exceeded": false,
                    "created_at": "2026-10-01T09:00:00+01:00"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "description": "Ask for a token with your API application's client id and secret\n(the OAuth client credentials grant), and send it as\n`Authorization: Bearer <token>`. Send `resource=https://subcontext.com/api/v1`\nwith the token request. A token asked for without it is refused.\nLeave `scope` out to get every scope the application has; name some\nto get only those. Tokens last two hours. Ask for a new one when it runs out.\n\nAn application with allowed origins (a browser application) can only\nhave `read` and `write`, and its tokens only work from pages on those\nwebsites. Requests for customer records (leads, outcomes, loyalty and\noutreach) need a server-only application, with no allowed origins.\n",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://subcontext.com/oauth/token",
            "scopes": {
              "read": "Read your products, journeys, quotes and similar (any GET request).",
              "write": "Change things (any POST, PATCH or PUT request), such as starting quotes and applications, taking payment, setting up policies, sending leads and recording outcomes. A token with write can read too.",
              "crm": "Send leads, and read what became of the leads this application sent. Server-only applications only.",
              "outcomes": "Report what became of any lead in your organisation, not only the ones this application sent. Server-only applications only."
            }
          }
        }
      }
    },
    "parameters": {
      "ProductSlug": {
        "name": "slug",
        "in": "path",
        "required": true,
        "description": "The product's slug, shown on its page in the dashboard under **Products**.",
        "schema": {
          "type": "string"
        },
        "example": "level-term-life"
      },
      "ProductSlugPath": {
        "name": "product_slug",
        "in": "path",
        "required": true,
        "description": "The product's slug, shown on its page in the dashboard under **Products**.",
        "schema": {
          "type": "string"
        },
        "example": "level-term-life"
      },
      "JourneySlug": {
        "name": "slug",
        "in": "path",
        "required": true,
        "description": "The journey's slug, from [List a product's journeys](/developers/api/reference/journeys#listJourneys).",
        "schema": {
          "type": "string"
        },
        "example": "express"
      },
      "ApplicationId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "The application's `id`.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "QuoteId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "The quote's `id`.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "MembershipRef": {
        "name": "external_ref",
        "in": "path",
        "required": true,
        "description": "Your own reference for the member (`external_member_ref`), or, before\nyou've confirmed the enrolment, Subcontext's membership id.\n",
        "schema": {
          "type": "string"
        },
        "example": "VIT-1001"
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "Carry on after the page this came from (its `next_cursor`). Leave it out to start at the beginning.",
        "schema": {
          "type": "string"
        }
      },
      "ShareToken": {
        "name": "X-Share-Token",
        "in": "header",
        "required": false,
        "description": "The application's `share_token`, from the answer that started it. A\nbrowser application sends it with every request about an\napplication that already exists, a replay of the request that\nstarted it included. Without it, or with another application's, the\nanswer is `404 not_found` (`409 idempotency_replay_unproven` on a\nreplay). A server-only application doesn't need it.\n",
        "schema": {
          "type": "string"
        },
        "example": "ytPVoqdUS9HP5G-dUgYpSSu4IjkbQdS0"
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "A value unique to this request in your system, so a retry doesn't do it twice.",
        "schema": {
          "type": "string"
        },
        "example": "quote-0001"
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "No token was sent, or it isn't valid because it has expired, was revoked (for\nexample because the application's secret was rotated), or was cut\nshort. Get a new token and try once more.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "invalid_token",
                "message": "The access token has expired. Ask for a new one."
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "The token can't be used here. It's missing a scope, it was used from\nthe wrong place (a server-only application's token in a browser, or a\nbrowser application's token from a server, another website or a\nrequest only server-only applications may make), or it wasn't asked\nfor with `resource=https://subcontext.com/api/v1`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "forbidden",
                "message": "origin 'https://www.example.com' is not allowlisted for this OAuth application"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "There's no such record in your organisation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "not_found",
                "message": "Resource not found"
              }
            }
          }
        }
      },
      "ApplicationNotFound": {
        "description": "There's no such application or quote in your organisation, or a\nbrowser application didn't send the application's `share_token` in\n`X-Share-Token`. Both get the same answer, so it never says whether\nan id exists.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "not_found",
                "message": "Resource not found. A browser application must send the application's share_token in the X-Share-Token header."
              }
            }
          }
        }
      },
      "ValidationFailed": {
        "description": "`validation_failed`: a required field is missing (`fields` names it).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "validation_failed",
                "message": "customer is required.",
                "fields": {
                  "customer": "is required"
                }
              }
            }
          }
        }
      },
      "QuoteNotBindable": {
        "description": "The quote can't be bought any more:\n\n- `quote_not_bindable`: it isn't the current quote (it was replaced, bought or rejected).\n- `quote_expired`: it has expired. Quote again.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "quote_expired",
                "message": "This quote expired on 2026-11-11."
              }
            }
          }
        }
      },
      "OutcomeReversed": {
        "description": "The outcome is reversed. `data` is the reversal, an outcome of its own pointing at the one it reverses in `reversal_of`.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/Outcome"
                }
              }
            },
            "example": {
              "data": {
                "id": "0199a3c2-8501-7a77-9df8-7cedfe0f1021",
                "event_id": null,
                "type": "sold",
                "contact_id": "0199a3c2-8200-7522-8ea3-2738a9bacbdc",
                "occurred_at": "2026-10-20T14:00:00+01:00",
                "source": "api",
                "deal_ref": "DEAL-5521",
                "product": "level-term",
                "values": {
                  "annual_premium": 14940,
                  "commission": 26892
                },
                "missing_values": [],
                "currency": "GBP",
                "reversed": false,
                "reversal_of": "0199a3c2-8500-7966-8ce7-6bdcedfe0f10"
              }
            }
          }
        }
      },
      "AlreadyReversed": {
        "description": "`already_reversed`: the outcome was already reversed, or is itself a reversal.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "already_reversed",
                "message": "This outcome is already reversed."
              }
            }
          }
        }
      },
      "MembershipUpdated": {
        "description": "The membership, as it is now.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "data"
              ],
              "properties": {
                "data": {
                  "$ref": "#/components/schemas/Membership"
                }
              }
            },
            "example": {
              "data": {
                "id": "0199a3c2-8800-7daa-8a2b-af1021324354",
                "programme_slug": "rewards",
                "programme_name": "Rewards",
                "policy_number": "POL-AB-P001-000042",
                "status": "active",
                "external_member_ref": "VIT-1001",
                "current_tier_key": "bronze",
                "cycle_points": 0,
                "cycle_started_on": "2026-10-12",
                "cycle_ends_on": "2027-10-12"
              }
            }
          }
        }
      },
      "MembershipInvalid": {
        "description": "`validation_failed`: the request can't be used (the message says\nwhy): an unknown `status`, nothing to change, or confirming without\n`external_member_ref`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "validation_failed",
                "message": "external_member_ref is required to confirm the enrolment",
                "fields": {
                  "status": "must be active, suspended or cancelled, with external_member_ref to confirm an enrolment"
                }
              }
            }
          }
        }
      },
      "MembershipConflict": {
        "description": "The membership's state won't allow it:\n\n- `membership_cancelled`: it's cancelled, and can't be changed.\n- `invalid_transition`: not from the status it's in (for example suspending a `pending` one).\n- `external_member_ref_mismatch`: it has a confirmed reference, and this one is different.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "invalid_transition",
                "message": "a pending membership can't become suspended"
              }
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "What went wrong. Every error from the API has this shape.",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "A short code for the kind of error, such as `invalid_token`, `forbidden`, `not_found` or `validation_failed`. Each code means one thing wherever it appears."
              },
              "message": {
                "type": "string",
                "description": "What went wrong and what to do about it, in plain English."
              },
              "fields": {
                "type": "object",
                "description": "When the error is about particular inputs, which ones and why,\nby name: a nested one with a dot (`customer.email`), one in a\nlist with its place (`components[0].term_years`). Left out\nwhen the error isn't about particular inputs.\n",
                "additionalProperties": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "NextCursor": {
        "type": [
          "string",
          "null"
        ],
        "description": "Pass as `cursor` for the next page. It's the place after this page's last item. An empty page gives back the `cursor` you sent (`null` if you sent none), so you can keep it and ask again later.\n"
      },
      "Product": {
        "type": "object",
        "description": "A product, with the terms it's sold on now.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "slug",
          "name",
          "product_type",
          "currency_code",
          "lifecycle_state",
          "cooldown_days",
          "inclusions",
          "exclusions",
          "cover_bounds",
          "covers"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The product's id."
          },
          "display_id": {
            "type": "string",
            "description": "The id as Subcontext shows it, `prod_` and the id."
          },
          "slug": {
            "type": "string",
            "description": "The product's slug, used in addresses such as `/api/v1/products/{slug}`."
          },
          "name": {
            "type": "string",
            "description": "The product's name, as customers see it."
          },
          "product_type": {
            "type": "string",
            "description": "What kind of product it is.",
            "enum": [
              "term",
              "decreasing_term",
              "whole_of_life",
              "critical_illness",
              "income_protection",
              "bundled",
              "child_cover",
              "healthcare"
            ]
          },
          "currency_code": {
            "type": "string",
            "description": "The currency it's priced in (ISO 4217), such as `GBP`."
          },
          "lifecycle_state": {
            "type": "string",
            "description": "Where the product is in its life. Only `production` products are sold to the public.",
            "enum": [
              "draft",
              "sandbox",
              "production",
              "archived"
            ]
          },
          "cooldown_days": {
            "type": "integer",
            "description": "The cooling-off period, in days, during which a customer can cancel for a full refund."
          },
          "inclusions": {
            "type": "array",
            "description": "What the product includes, as short sentences for customers.",
            "items": {
              "type": "string"
            }
          },
          "exclusions": {
            "type": "array",
            "description": "What the product doesn't cover, as short sentences for customers.",
            "items": {
              "type": "string"
            }
          },
          "cover_bounds": {
            "$ref": "#/components/schemas/CoverBounds"
          },
          "covers": {
            "type": "array",
            "description": "The covers that make up the product, such as life cover with critical illness cover added.",
            "items": {
              "$ref": "#/components/schemas/Cover"
            }
          }
        }
      },
      "CoverBounds": {
        "type": "object",
        "description": "The limits for a quote across all the product's covers: the lowest\nand highest amount, age at the start and term. Each is `null` when the\nproduct has no covers (or, for terms, no cover with a fixed term).\n",
        "additionalProperties": false,
        "required": [
          "sum_assured_min_pence",
          "sum_assured_max_pence",
          "age_min",
          "age_max",
          "term_min",
          "term_max"
        ],
        "properties": {
          "sum_assured_min_pence": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The smallest amount of cover, in whole pence (the smallest unit of the product's currency)."
          },
          "sum_assured_max_pence": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The largest amount of cover, in whole pence."
          },
          "age_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The youngest age, in years, at which cover can start."
          },
          "age_max": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The oldest age at which cover can start."
          },
          "term_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The shortest term, in years."
          },
          "term_max": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The longest term, in years."
          }
        }
      },
      "Cover": {
        "type": "object",
        "description": "One cover in a product, with the limits it's sold within.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "cover_type",
          "cover_index",
          "sum_assured_min_pence",
          "sum_assured_max_pence",
          "age_at_entry_min",
          "age_at_entry_max",
          "term_years_min",
          "term_years_max",
          "max_age_at_expiry",
          "premium_basis",
          "review_period_years",
          "minimum_premium_pence",
          "ci_payout_basis",
          "survival_period_days",
          "indexation_method",
          "benefit_basis",
          "title",
          "pricing_basis",
          "member_premium_pence",
          "members_factor",
          "opt_in_factor"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The cover's id."
          },
          "display_id": {
            "type": "string",
            "description": "The id as Subcontext shows it, `cov_` and the id."
          },
          "cover_type": {
            "type": "string",
            "description": "What the cover pays out for.",
            "enum": [
              "life",
              "critical_illness",
              "income_protection",
              "accidental_death",
              "child_benefit",
              "healthcare"
            ]
          },
          "cover_index": {
            "type": "integer",
            "description": "The cover's position in the product, starting at 0."
          },
          "sum_assured_min_pence": {
            "type": "integer",
            "description": "The smallest amount of cover, in whole pence (the smallest unit of the product's currency). For a monthly benefit, the yearly amount."
          },
          "sum_assured_max_pence": {
            "type": "integer",
            "description": "The largest amount of cover, in whole pence."
          },
          "age_at_entry_min": {
            "type": "integer",
            "description": "The youngest age, in years, at which this cover can start."
          },
          "age_at_entry_max": {
            "type": "integer",
            "description": "The oldest age at which this cover can start."
          },
          "term_years_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The shortest term in years, or `null` for cover with no fixed term."
          },
          "term_years_max": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The longest term in years, or `null` for cover with no fixed term."
          },
          "max_age_at_expiry": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The oldest the person can be when the cover ends, if there's a limit."
          },
          "premium_basis": {
            "type": "string",
            "description": "Whether the price is fixed for the whole term (`guaranteed`) or reviewed from time to time (`reviewable`).",
            "enum": [
              "guaranteed",
              "reviewable"
            ]
          },
          "review_period_years": {
            "type": [
              "integer",
              "null"
            ],
            "description": "For reviewable premiums, how often in years the price is reviewed."
          },
          "minimum_premium_pence": {
            "type": "integer",
            "description": "The lowest monthly premium, in pence (or the smallest unit of the product's currency)."
          },
          "ci_payout_basis": {
            "type": "string",
            "description": "For critical illness cover, whether it pays out on top of life cover (`additional`) or as an early part of it (`accelerated`).",
            "enum": [
              "additional",
              "accelerated"
            ]
          },
          "survival_period_days": {
            "type": "integer",
            "description": "How many days the person must survive after a diagnosis for a critical illness claim."
          },
          "indexation_method": {
            "type": "string",
            "description": "How the amount of cover changes over the term.",
            "enum": [
              "none",
              "rpi",
              "fixed_percent",
              "decreasing"
            ]
          },
          "benefit_basis": {
            "type": "string",
            "description": "Whether the cover pays a lump sum or a monthly benefit.",
            "enum": [
              "lump_sum",
              "monthly_benefit"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "The cover's name where its type alone doesn't say which it is, such as one level of a group plan (`Diagnosis`); otherwise `null`."
          },
          "pricing_basis": {
            "type": "string",
            "description": "How the cover is priced: by underwriting and rate tables (`rated`),\nfrom a fixed list of cover levels, each with its own price\n(`fixed_tiers`), or at a monthly price for each person on it\n(`per_member`, an employer's group plan). A per-member cover has\nno amount of cover or term: its quote is sized by headcounts.\n",
            "enum": [
              "rated",
              "fixed_tiers",
              "per_member"
            ]
          },
          "member_premium_pence": {
            "type": [
              "integer",
              "null"
            ],
            "description": "For a `per_member` cover, the monthly price for each person on it, in whole pence; otherwise `null`."
          },
          "members_factor": {
            "type": [
              "string",
              "null"
            ],
            "description": "For a `per_member` cover, the key of the answer that holds how many people it covers, sent in `risk_factors`; otherwise `null`."
          },
          "opt_in_factor": {
            "type": [
              "string",
              "null"
            ],
            "description": "For a `per_member` add-on, the key of the yes or no answer that adds it to the plan (it then covers the number of people `members_factor` names); `null` for a cover that's always included, and for any other cover."
          }
        }
      },
      "Journey": {
        "type": "object",
        "description": "One of a product's journeys.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "slug",
          "name",
          "description",
          "journey_loading",
          "position",
          "lifecycle_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_id": {
            "type": "string",
            "description": "The id as Subcontext shows it, `jrn_` and the id."
          },
          "slug": {
            "type": "string",
            "description": "The journey's slug, used in addresses and to start an application."
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "journey_loading": {
            "type": "string",
            "description": "A multiplier this journey applies to the price, as a decimal string (`\"1.00\"` is none)."
          },
          "position": {
            "type": "integer",
            "description": "Its place among the product's journeys, from 0."
          },
          "lifecycle_state": {
            "type": "string",
            "enum": [
              "draft",
              "sandbox",
              "production",
              "archived"
            ]
          }
        }
      },
      "Question": {
        "type": "object",
        "description": "One question in a journey.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "key",
          "label",
          "help_text",
          "question_type",
          "position",
          "required",
          "validation",
          "group_key",
          "group_label",
          "lookup_source",
          "suggestions",
          "answer_options"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_id": {
            "type": "string",
            "description": "The id as Subcontext shows it, `qst_` and the id."
          },
          "key": {
            "type": "string",
            "description": "The question's key, which an answer is saved under."
          },
          "label": {
            "type": "string",
            "description": "The question, as the customer sees it."
          },
          "help_text": {
            "type": [
              "string",
              "null"
            ],
            "description": "Help shown with the question."
          },
          "question_type": {
            "type": "string",
            "description": "What kind of answer it takes: a `date` (`YYYY-MM-DD`), free text\n(`string`), a `number` or whole number (`integer`), yes or no\n(`boolean`), one option (`enum`) or several (`multi_select`).\nA `derived` question is worked out from others (such as BMI from height and weight). Don't ask it.\n",
            "enum": [
              "date",
              "string",
              "number",
              "integer",
              "boolean",
              "enum",
              "multi_select",
              "derived"
            ]
          },
          "position": {
            "type": "integer",
            "description": "Its place in the journey."
          },
          "required": {
            "type": "boolean"
          },
          "validation": {
            "type": "object",
            "description": "Limits on the answer, such as `min` and `max`.",
            "additionalProperties": true
          },
          "group_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Questions with the same group belong together on a page."
          },
          "group_label": {
            "type": [
              "string",
              "null"
            ],
            "description": "The group's heading."
          },
          "lookup_source": {
            "type": [
              "string",
              "null"
            ],
            "description": "For free-text questions answered from a list (such as `occupations`), which list."
          },
          "suggestions": {
            "type": [
              "array",
              "null"
            ],
            "description": "For a question with a `lookup_source`, the answers to suggest as the customer types. Match on `search`; show and send `label`.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "label",
                "search"
              ],
              "properties": {
                "label": {
                  "type": "string"
                },
                "search": {
                  "type": "string",
                  "description": "The label and other words for it, to match against."
                }
              }
            }
          },
          "answer_options": {
            "type": "array",
            "description": "For `enum` and `multi_select` questions, the options, in order. Empty for other kinds.",
            "items": {
              "$ref": "#/components/schemas/AnswerOption"
            }
          },
          "ask_if": {
            "type": "object",
            "description": "Present when the question is only asked sometimes. A condition on earlier answers, such as `{ \"key\": \"smoker\", \"equals\": true }`.",
            "additionalProperties": true
          }
        }
      },
      "AnswerOption": {
        "type": "object",
        "description": "One option for a choice question.",
        "additionalProperties": false,
        "required": [
          "id",
          "value",
          "label",
          "position"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "value": {
            "type": "string",
            "description": "What to send as the answer."
          },
          "label": {
            "type": "string",
            "description": "What the customer sees."
          },
          "position": {
            "type": "integer"
          },
          "terminal_outcome": {
            "type": "string",
            "description": "Present when choosing this ends the application, and how.",
            "enum": [
              "decline",
              "refer",
              "postpone"
            ]
          },
          "terminal_reason_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "A short code for why."
          },
          "terminal_reason_message": {
            "type": [
              "string",
              "null"
            ],
            "description": "What to tell the customer."
          }
        }
      },
      "Presentation": {
        "type": "object",
        "description": "How a journey is presented as a form: its pages (stages), in order.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "slug",
          "name",
          "template_key",
          "is_default",
          "stages"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_id": {
            "type": "string",
            "description": "The id as Subcontext shows it, `prs_` and the id."
          },
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "template_key": {
            "type": "string",
            "description": "The template it's built from."
          },
          "is_default": {
            "type": "boolean",
            "description": "Whether it's the journey's default presentation."
          },
          "stages": {
            "type": "array",
            "description": "The stages, in order.",
            "items": {
              "$ref": "#/components/schemas/Stage"
            }
          }
        }
      },
      "Stage": {
        "type": "object",
        "description": "One page (stage) of a presentation.",
        "additionalProperties": false,
        "required": [
          "id",
          "key",
          "position",
          "stage_type",
          "title",
          "cta_label",
          "config"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The stage's id."
          },
          "key": {
            "type": "string",
            "description": "The stage's key, unique in the presentation."
          },
          "position": {
            "type": "integer"
          },
          "stage_type": {
            "type": "string",
            "description": "What the stage does, such as `personal_details` (the customer's\ndetails), `cover_capture` (amount and term), `questions`,\n`quote`, `payment`, `soft_identity`, `interstitial`,\n`reflection`, `handoff` or `market_quote` (a whole-of-market comparison).\n"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "cta_label": {
            "type": [
              "string",
              "null"
            ],
            "description": "The button's wording, if not the usual."
          },
          "config": {
            "type": "object",
            "description": "The stage's settings, such as which fields a details stage asks for.",
            "additionalProperties": true
          },
          "heading": {
            "type": "string",
            "description": "A heading, when the stage has one."
          },
          "intro": {
            "type": "string",
            "description": "An introduction, when the stage has one."
          },
          "consent_notice": {
            "type": "string",
            "description": "On the details stage, your firm's wording for what giving these details means. Show it under the fields."
          },
          "consent_opt_outs": {
            "type": "array",
            "description": "On the details stage, boxes to tick to say no to something. Send the ticked ones as `consent_answers`.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "key",
                "label"
              ],
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              }
            }
          },
          "marketing": {
            "$ref": "#/components/schemas/MarketingQuestion"
          }
        }
      },
      "MarketingQuestion": {
        "type": "object",
        "description": "Your firm's marketing question. Answer it with [Record marketing choices](/developers/api/reference/quotes-and-applications#recordMarketingPreference).",
        "additionalProperties": false,
        "required": [
          "capture_point",
          "title",
          "question",
          "options"
        ],
        "properties": {
          "capture_point": {
            "type": "string"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "question": {
            "type": [
              "string",
              "null"
            ]
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "key",
                "label",
                "type"
              ],
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "description": "Whether ticking the box says yes (`opt_in`) or no (`opt_out`).",
                  "enum": [
                    "opt_in",
                    "opt_out"
                  ]
                }
              }
            }
          }
        }
      },
      "ReplacesIdempotencyKey": {
        "type": "string",
        "description": "On a request sent again under a new `Idempotency-Key` because the\nfirst answer never arrived, the key it was first sent with. The\napplication that key made is closed so nobody follows it up, if it\nwas made in the last hour, hasn't changed since, and is for the same\nproduct, journey and customer. Otherwise it's left as it was.\n"
      },
      "CustomerInput": {
        "type": "object",
        "description": "A person's details. Every field is optional on its own, but a customer needs a first name, last name and email address.",
        "properties": {
          "title": {
            "type": "string"
          },
          "first_name": {
            "type": "string"
          },
          "last_name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Customers are found by email address within your organisation. A browser application never changes an existing customer's record unless its application created it."
          },
          "phone_number": {
            "type": "string"
          },
          "dob": {
            "type": "string",
            "format": "date",
            "description": "Date of birth, `YYYY-MM-DD`."
          },
          "postal_code": {
            "type": "string"
          },
          "address_line1": {
            "type": "string"
          },
          "address_line2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "country": {
            "type": "string"
          }
        }
      },
      "ProvenanceInput": {
        "type": "object",
        "description": "Where the customer was when they filled it in, for your reports on\nwhat brings people in: `page_url` (with its `utm_` tags), `referrer`,\n`page_title`, `locale`, `timezone`, `utm` and `click_ids` (such as\n`gclid`). Everything is checked and tidied before it's kept, and personal details in addresses are removed.\n",
        "additionalProperties": true
      },
      "ApplicationEnvelope": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Application"
          }
        }
      },
      "Application": {
        "type": "object",
        "description": "One customer's request for cover.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "status",
          "idempotency_key",
          "product_id",
          "journey_id",
          "customer",
          "joint_customer",
          "risk_factors",
          "cover_amount_pence",
          "term_years",
          "policy_id",
          "abandoned_reason",
          "presentation",
          "inline_bacs_mandate",
          "direct_debit_first",
          "stripe_test_mode",
          "market_quotes",
          "marketing_answered",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_id": {
            "type": "string",
            "description": "The id as Subcontext shows it, `app_` and the id."
          },
          "status": {
            "type": "string",
            "description": "Where the application is: `anonymous` (no customer yet),\n`in_capture` (being filled in), `quoted`, `referred` (with your\nteam), `declined`, `postponed`, `bound` (the policy is set up),\n`handed_off` (sent to another provider), `abandoned`.\n",
            "enum": [
              "started",
              "in_capture",
              "quoted",
              "referred",
              "bound",
              "declined",
              "postponed",
              "abandoned",
              "anonymous",
              "handed_off"
            ]
          },
          "idempotency_key": {
            "type": "string",
            "description": "The idempotency key it was started with (one is made up when you don't send one)."
          },
          "product_id": {
            "type": "string",
            "format": "uuid"
          },
          "journey_id": {
            "type": "string",
            "format": "uuid"
          },
          "customer": {
            "description": "The person to be covered, or `null` before they're known.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApplicationCustomer"
              },
              {
                "type": "null"
              }
            ]
          },
          "joint_customer": {
            "description": "For joint cover, the second person; otherwise `null`.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApplicationCustomer"
              },
              {
                "type": "null"
              }
            ]
          },
          "risk_factors": {
            "type": "object",
            "description": "The answers so far, by question key.",
            "additionalProperties": true
          },
          "cover_amount_pence": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The amount of cover asked for, in pence."
          },
          "term_years": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The term asked for, in years."
          },
          "policy_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The policy, once it's set up."
          },
          "abandoned_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "presentation": {
            "description": "The presentation it's being filled in on, or `null`.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/Presentation"
              },
              {
                "type": "null"
              }
            ]
          },
          "inline_bacs_mandate": {
            "type": "boolean",
            "description": "`true` when the Direct Debit is set up on Stripe's form ([Start a Direct Debit mandate](/developers/api/reference/checkout#createBacsSetupIntent)) rather than by sending bank details."
          },
          "direct_debit_first": {
            "type": "boolean",
            "description": "`true` when the first premium is taken by Direct Debit, so there's no card payment."
          },
          "stripe_test_mode": {
            "type": "boolean",
            "description": "`true` when this product's payments use Stripe's test account (use Stripe's test card and bank details)."
          },
          "market_quotes": {
            "description": "For a whole-of-market product, the latest market search; otherwise `null`.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/MarketQuotes"
              },
              {
                "type": "null"
              }
            ]
          },
          "marketing_answered": {
            "type": "boolean",
            "description": "Whether the customer has answered your firm's marketing question."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "share_token": {
            "type": "string",
            "description": "The key to this application for the quote form and webchat. Only included where you may see it."
          }
        }
      },
      "ApplicationCustomer": {
        "type": "object",
        "description": "A person on an application.",
        "additionalProperties": false,
        "required": [
          "id",
          "title",
          "first_name",
          "last_name",
          "email",
          "phone_number",
          "dob",
          "postal_code",
          "address_line1",
          "address_line2",
          "city",
          "country"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "first_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "dob": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Date of birth, `YYYY-MM-DD`."
          },
          "postal_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "address_line1": {
            "type": [
              "string",
              "null"
            ]
          },
          "address_line2": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Knockout": {
        "type": "object",
        "description": "The answer that ends the application.",
        "additionalProperties": false,
        "required": [
          "outcome",
          "question_key",
          "value"
        ],
        "properties": {
          "outcome": {
            "type": "string",
            "enum": [
              "decline",
              "refer",
              "postpone"
            ]
          },
          "question_key": {
            "type": "string"
          },
          "value": {
            "type": "string"
          },
          "reason_code": {
            "type": "string"
          },
          "message": {
            "type": "string",
            "description": "What to tell the customer."
          }
        }
      },
      "MarketQuotes": {
        "type": "object",
        "description": "A whole-of-market search and its results.",
        "additionalProperties": false,
        "required": [
          "request_id",
          "status",
          "fetched_at",
          "expires_at",
          "stale",
          "provider_count",
          "failure_code",
          "selected_result_id",
          "results"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "description": "`pending` and `fetching` while it runs; `completed` or `failed` when done; `superseded` when a newer search replaced it.",
            "enum": [
              "pending",
              "fetching",
              "completed",
              "failed",
              "superseded"
            ]
          },
          "fetched_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the quotes stop being valid."
          },
          "stale": {
            "type": "boolean",
            "description": "`true` when the answers have changed since the search. Search again."
          },
          "provider_count": {
            "type": "integer",
            "description": "How many providers answered."
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "selected_result_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The quote the customer chose, if they have."
          },
          "results": {
            "type": "array",
            "description": "The quotes, cheapest first.",
            "items": {
              "$ref": "#/components/schemas/MarketQuoteResult"
            }
          }
        }
      },
      "MarketQuoteResult": {
        "type": "object",
        "description": "One provider's quote.",
        "additionalProperties": false,
        "required": [
          "ordinal",
          "result_id",
          "provider_name",
          "logo_url",
          "product_name",
          "premium_pence",
          "premium_monthly",
          "plan_fee_pence",
          "status",
          "status_reason",
          "variations",
          "features",
          "evidence_required",
          "further_underwriting",
          "standard_or_underwritten",
          "expiry_date",
          "selected"
        ],
        "properties": {
          "ordinal": {
            "type": "integer",
            "description": "Its place in the list, from 1."
          },
          "result_id": {
            "type": "string",
            "format": "uuid",
            "description": "What to send to [Choose a market quote](/developers/api/reference/quotes-and-applications#selectMarketQuote)."
          },
          "provider_name": {
            "type": "string"
          },
          "logo_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "product_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "premium_pence": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The monthly premium, in pence."
          },
          "premium_monthly": {
            "type": [
              "string",
              "null"
            ],
            "description": "The monthly premium, written out (`£11.80`)."
          },
          "plan_fee_pence": {
            "type": [
              "integer",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "description": "Whether the provider gave a usable quote (`success`)."
          },
          "status_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "variations": {
            "type": "array",
            "description": "Where the provider changed what was asked for (such as a shorter term), each with `name`, `original_value` and `new_value`.",
            "items": {
              "type": "object"
            }
          },
          "features": {
            "type": "array",
            "description": "What the policy includes.",
            "items": {
              "type": "object"
            }
          },
          "evidence_required": {
            "type": "boolean",
            "description": "Whether the provider needs medical evidence."
          },
          "further_underwriting": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "standard_or_underwritten": {
            "type": [
              "string",
              "null"
            ]
          },
          "expiry_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "selected": {
            "type": "boolean"
          }
        }
      },
      "Quote": {
        "type": "object",
        "description": "A price for an application.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "reference",
          "status",
          "basis",
          "decision",
          "currency_code",
          "total_premium_monthly_pence",
          "policy_fee_pence",
          "bundle_discount_pence",
          "issued_at",
          "expires_at",
          "accepted_at",
          "superseded_by_id",
          "assumptions",
          "components",
          "premium_illustration"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_id": {
            "type": "string",
            "description": "The id as Subcontext shows it, `quo_` and the id."
          },
          "reference": {
            "type": "string",
            "description": "The quote's reference, for the customer and your team."
          },
          "status": {
            "type": "string",
            "description": "`issued` (current, can be bought), `accepted`, `superseded` (replaced by a newer quote), `expired` or `rejected`.",
            "enum": [
              "issued",
              "superseded",
              "expired",
              "accepted",
              "rejected"
            ]
          },
          "basis": {
            "type": "string",
            "description": "One person (`single`) or two (`joint`).",
            "enum": [
              "single",
              "joint"
            ]
          },
          "decision": {
            "type": "string",
            "description": "Offered at standard rates, with a rating on some cover (`accept_rated`), or both across its covers (`mixed`).",
            "enum": [
              "accept_standard",
              "accept_rated",
              "mixed"
            ]
          },
          "currency_code": {
            "type": "string"
          },
          "total_premium_monthly_pence": {
            "type": "integer",
            "description": "The monthly premium, in whole pence, with any policy fee and bundle discount."
          },
          "policy_fee_pence": {
            "type": "integer",
            "description": "The policy fee included each month, in pence."
          },
          "bundle_discount_pence": {
            "type": "integer",
            "description": "The discount for taking several covers together, in pence a month."
          },
          "issued_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "After this, the quote can't be bought."
          },
          "accepted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "superseded_by_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The quote that replaced it."
          },
          "assumptions": {
            "type": "array",
            "description": "For a price part way through, the answers it assumed because they weren't given yet, such as `{ \"key\": \"smoker\", \"assumed_value\": false }`. Empty for a full quote.",
            "items": {
              "type": "object"
            }
          },
          "components": {
            "type": "array",
            "description": "The price of each cover.",
            "items": {
              "$ref": "#/components/schemas/QuoteComponent"
            }
          },
          "premium_illustration": {
            "description": "For cover with no fixed end, what the premiums would add up to by a natural end date, worded for the customer; otherwise `null`.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/PremiumIllustration"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "QuoteComponent": {
        "type": "object",
        "description": "One cover's price.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "cover_id",
          "cover_type",
          "component_index",
          "sum_assured_pence",
          "term_years",
          "decision",
          "rating_pct",
          "premium_monthly_pence",
          "premium_annual_pence",
          "exclusions",
          "reasons",
          "lives",
          "member_count",
          "title"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_id": {
            "type": "string",
            "description": "The id as Subcontext shows it, `qco_` and the id."
          },
          "cover_id": {
            "type": "string",
            "format": "uuid"
          },
          "cover_type": {
            "type": "string",
            "enum": [
              "life",
              "critical_illness",
              "income_protection",
              "accidental_death",
              "child_benefit",
              "healthcare"
            ]
          },
          "component_index": {
            "type": "integer"
          },
          "sum_assured_pence": {
            "type": "integer",
            "description": "The amount of cover, in whole pence (`0` for a `per_member` cover, which is sized by `member_count`)."
          },
          "term_years": {
            "type": [
              "integer",
              "null"
            ]
          },
          "decision": {
            "type": "string",
            "enum": [
              "accept_standard",
              "accept_rated"
            ]
          },
          "rating_pct": {
            "type": "integer",
            "description": "The price as a percentage of the standard rate (`100` is standard)."
          },
          "premium_monthly_pence": {
            "type": "integer",
            "description": "The monthly premium, in whole pence."
          },
          "premium_annual_pence": {
            "type": "integer",
            "description": "The yearly premium, in whole pence."
          },
          "exclusions": {
            "type": "array",
            "description": "What this cover won't pay out for, for this customer.",
            "items": {}
          },
          "reasons": {
            "type": "array",
            "description": "Why it was rated, if it was.",
            "items": {}
          },
          "lives": {
            "type": "array",
            "description": "On joint cover, the outcome for each person.",
            "items": {
              "type": "object"
            }
          },
          "member_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "For a `per_member` cover, how many people it was priced for (its price is that many times the cover's `member_premium_pence`); otherwise `null`."
          },
          "title": {
            "type": "string",
            "description": "The cover's name, as customers see it, such as `Diagnosis` on a group plan (`12 × Diagnosis`) or `Life` for life cover."
          }
        }
      },
      "PremiumIllustration": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "until",
          "until_label",
          "months",
          "total",
          "total_pence",
          "explanation"
        ],
        "properties": {
          "until": {
            "type": "string",
            "format": "date"
          },
          "until_label": {
            "type": "string",
            "description": "The end date's description, such as \"age 90\"."
          },
          "months": {
            "type": "integer"
          },
          "total": {
            "type": "string",
            "description": "The total, written out."
          },
          "total_pence": {
            "type": "integer",
            "description": "The total, in whole pence."
          },
          "explanation": {
            "type": "string",
            "description": "A sentence for the customer."
          }
        }
      },
      "RuleExecution": {
        "type": "object",
        "description": "How one cover was assessed: the underwriting decision and the rate it was priced at.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "cover_id",
          "mode",
          "decision",
          "rating_pct",
          "exclusions",
          "premium_monthly_pence",
          "premium_annual_pence",
          "rate_per_mille",
          "decline_reasons",
          "referral_reasons",
          "executed_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_id": {
            "type": "string"
          },
          "cover_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "mode": {
            "type": "string",
            "enum": [
              "live",
              "shadow",
              "test"
            ]
          },
          "decision": {
            "type": [
              "string",
              "null"
            ],
            "description": "`accept_standard`, `accept_rated`, `refer`, `decline` or `postpone`."
          },
          "rating_pct": {
            "type": [
              "integer",
              "null"
            ]
          },
          "exclusions": {
            "type": "array",
            "items": {}
          },
          "premium_monthly_pence": {
            "type": [
              "integer",
              "null"
            ],
            "description": "In whole pence, before any policy fee."
          },
          "premium_annual_pence": {
            "type": [
              "integer",
              "null"
            ],
            "description": "In whole pence."
          },
          "rate_per_mille": {
            "type": [
              "string",
              "number",
              "null"
            ],
            "description": "The rate per £1,000 of cover."
          },
          "decline_reasons": {
            "type": "array",
            "items": {}
          },
          "referral_reasons": {
            "type": "array",
            "items": {}
          },
          "executed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "trace": {
            "type": "array",
            "description": "The steps of the assessment, including the rules and rate tables it used. Only for a server-only application.",
            "items": {}
          }
        }
      },
      "QuoteResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "application",
              "quote",
              "executions"
            ],
            "properties": {
              "application": {
                "$ref": "#/components/schemas/Application"
              },
              "quote": {
                "description": "The quote, or `null` when no price can be offered.",
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Quote"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "executions": {
                "type": "array",
                "description": "How each cover was assessed.",
                "items": {
                  "$ref": "#/components/schemas/RuleExecution"
                }
              }
            }
          }
        }
      },
      "PolicyEnvelope": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Policy"
          }
        }
      },
      "Policy": {
        "type": "object",
        "description": "A policy, with the customer's links to it.",
        "additionalProperties": false,
        "required": [
          "id",
          "display_id",
          "policy_number",
          "basis",
          "joint_customer_name",
          "currency_code",
          "commencement_date",
          "total_premium_monthly_pence",
          "overall_decision",
          "pas_sync_status",
          "bound_at",
          "cancelled_at",
          "components",
          "cessions",
          "first_premium_record",
          "policy_hub_path",
          "schedule_path",
          "documents",
          "first_collection_on",
          "collection_day_of_month",
          "wrap_up"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_id": {
            "type": "string",
            "description": "The id as Subcontext shows it, `pol_` and the id."
          },
          "policy_number": {
            "type": "string"
          },
          "basis": {
            "type": "string",
            "enum": [
              "single",
              "joint"
            ]
          },
          "joint_customer_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "For joint cover, the second person's name."
          },
          "currency_code": {
            "type": "string"
          },
          "commencement_date": {
            "type": "string",
            "format": "date",
            "description": "When cover starts."
          },
          "total_premium_monthly_pence": {
            "type": "integer",
            "description": "The monthly premium, in whole pence."
          },
          "overall_decision": {
            "type": "string",
            "enum": [
              "accept_standard",
              "accept_rated",
              "mixed"
            ]
          },
          "pas_sync_status": {
            "type": "string",
            "description": "Whether the policy has reached your policy administration system, if you use one.",
            "enum": [
              "pending",
              "synced",
              "failed_reconciling",
              "failed_unrecoverable"
            ]
          },
          "bound_at": {
            "type": "string",
            "format": "date-time"
          },
          "cancelled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "components": {
            "type": "array",
            "description": "The covers.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "display_id",
                "cover_id",
                "cover_type",
                "component_index",
                "sum_assured_pence",
                "term_years",
                "premium_monthly_pence",
                "decision",
                "rating_pct",
                "exclusions",
                "lives",
                "commencement_date",
                "cancelled_at"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "display_id": {
                  "type": "string"
                },
                "cover_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "cover_type": {
                  "type": "string"
                },
                "component_index": {
                  "type": "integer"
                },
                "sum_assured_pence": {
                  "type": "integer",
                  "description": "The amount of cover, in whole pence."
                },
                "term_years": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "premium_monthly_pence": {
                  "type": "integer",
                  "description": "The monthly premium, in whole pence."
                },
                "decision": {
                  "type": "string"
                },
                "rating_pct": {
                  "type": "integer"
                },
                "exclusions": {
                  "type": "array",
                  "items": {}
                },
                "lives": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                },
                "commencement_date": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date"
                },
                "cancelled_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                }
              }
            }
          },
          "cessions": {
            "type": "array",
            "description": "Reinsurance arrangements for the cover, if your firm shares its risk. Amounts are whole pence (`retained_pence`, `ceded_pence`, `first_ceded_premium_pence`).",
            "items": {
              "type": "object"
            }
          },
          "first_premium_record": {
            "description": "The first premium's payment, or `null` before there is one.",
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "id",
                  "display_id",
                  "kind",
                  "amount_pence",
                  "currency_code",
                  "status",
                  "source",
                  "processor",
                  "processor_reference",
                  "occurred_at"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "display_id": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string"
                  },
                  "amount_pence": {
                    "type": "integer",
                    "description": "In whole pence."
                  },
                  "currency_code": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string"
                  },
                  "processor": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "processor_reference": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The payment's id at the processor (Stripe's PaymentIntent id)."
                  },
                  "occurred_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "policy_hub_path": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where the customer manages their policy."
          },
          "schedule_path": {
            "type": [
              "string",
              "null"
            ],
            "description": "The policy schedule, or `null` when the policy is managed elsewhere."
          },
          "documents": {
            "type": "array",
            "description": "The policy's documents, for the customer.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "kind",
                "name",
                "path"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "kind": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "path": {
                  "type": "string",
                  "description": "Its address."
                }
              }
            }
          },
          "first_collection_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "When the first Direct Debit collection is due."
          },
          "collection_day_of_month": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The day of the month premiums are collected."
          },
          "wrap_up": {
            "description": "Your firm's closing words after purchase, when it has them; otherwise `null`.",
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "points",
                  "next_steps",
                  "marketing"
                ],
                "properties": {
                  "points": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "next_steps": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "marketing": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/MarketingQuestion"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "SaleStep": {
        "type": "string",
        "description": "A step the sale owes before the policy can be set up.",
        "enum": [
          "demands_and_needs",
          "key_documents_before_bind",
          "cancellation_rights_before_bind",
          "confirm_before_purchase"
        ]
      },
      "BeforeYouBuy": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "show",
          "steps",
          "sellable",
          "demands_and_needs",
          "key_documents",
          "cancellation",
          "confirmation"
        ],
        "properties": {
          "show": {
            "type": "boolean",
            "description": "Whether to show the screen at all."
          },
          "steps": {
            "type": "array",
            "description": "The steps still owed.",
            "items": {
              "$ref": "#/components/schemas/SaleStep"
            }
          },
          "sellable": {
            "type": "boolean",
            "description": "`false` when the product can't be bought on a form. Offer a conversation instead."
          },
          "demands_and_needs": {
            "type": [
              "string",
              "null"
            ],
            "description": "The product's demands and needs statement, to show and have the customer confirm."
          },
          "key_documents": {
            "type": "array",
            "description": "Documents to give the customer before they buy.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "document_id",
                "version_id",
                "kind",
                "name",
                "url"
              ],
              "properties": {
                "document_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "version_id": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uuid"
                },
                "kind": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "description": "Where to read it."
                }
              }
            }
          },
          "cancellation": {
            "description": "The customer's right to cancel, to show them; or `null`.",
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "days",
                  "statement"
                ],
                "properties": {
                  "days": {
                    "type": "integer"
                  },
                  "statement": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "confirmation": {
            "description": "A read-back of what they're buying, to ask them to agree to; or `null`.",
            "anyOf": [
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "intro",
                  "points",
                  "question"
                ],
                "properties": {
                  "intro": {
                    "type": "string"
                  },
                  "points": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "question": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "Ingest": {
        "type": "object",
        "description": "A lead you sent, and what became of it. Fields with nothing to say are left out.",
        "additionalProperties": false,
        "required": [
          "id",
          "status",
          "source",
          "received_at",
          "facts_written",
          "fields_proposed",
          "activities_written",
          "truncated",
          "explanation"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "description": "`received`, `resolving` and `extracting` while it's being worked\non. Then `applied` (it's on the lead `contact_id`),\n`needs_review` (a person must decide who it's about), `held`\n(it didn't meet the campaign's rules; a person can accept it),\n`deferred` (paused, carries on by itself), `failed` or\n`discarded`.\n",
            "enum": [
              "received",
              "resolving",
              "extracting",
              "applied",
              "needs_review",
              "deferred",
              "failed",
              "discarded",
              "held"
            ]
          },
          "source": {
            "type": "string"
          },
          "source_reference": {
            "type": "string",
            "description": "Your reference, if you sent one."
          },
          "received_at": {
            "type": "string",
            "format": "date-time"
          },
          "processed_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was finished with."
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "The lead it was applied to. Use it with [Get a lead](/developers/api/reference/crm-leads#getLead)."
          },
          "facts_written": {
            "type": "integer",
            "description": "How many facts about the person were recorded."
          },
          "fields_proposed": {
            "type": "integer",
            "description": "How many values were put to your team because they differ from what's held."
          },
          "activities_written": {
            "type": "integer"
          },
          "truncated": {
            "type": "boolean",
            "description": "Whether the lead was too long to read in full."
          },
          "retry_after": {
            "type": "string",
            "format": "date-time",
            "description": "For a deferred lead, when it carries on."
          },
          "error": {
            "type": "string",
            "description": "Why it was deferred or failed."
          },
          "validation_failures": {
            "type": "array",
            "description": "For a held lead, which of the campaign's rules it didn't meet, in your field names.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "field",
                "rule",
                "reason"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "rule": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "reason": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "provenance": {
            "type": "object",
            "description": "Where the lead was captured, as Subcontext understood it from your `provenance` and `context`.",
            "additionalProperties": true
          },
          "explanation": {
            "type": "string",
            "description": "What happened, in words."
          },
          "duplicate": {
            "type": "boolean",
            "description": "Only in the answer to [Send a lead](/developers/api/reference/crm-leads#createIngest): `true` when this was the same lead as one already received, which is what you get back."
          }
        }
      },
      "Lead": {
        "type": "object",
        "description": "Where a lead is now, without the person's details.",
        "additionalProperties": false,
        "required": [
          "contact_id",
          "external_system_id",
          "status",
          "terminal",
          "stage",
          "stage_entered_at",
          "owner_assigned",
          "score",
          "campaign_id",
          "first_touched_at",
          "last_touched_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "The lead's id."
          },
          "external_system_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The lead's id in your organisation's own CRM, if it has one."
          },
          "status": {
            "type": "string",
            "description": "The lead's outcome so far.",
            "enum": [
              "open",
              "won",
              "lost",
              "dormant",
              "disqualified",
              "duplicate",
              "invalid",
              "not_interested",
              "ineligible"
            ]
          },
          "terminal": {
            "type": "boolean",
            "description": "Whether that's final (won, lost, or ruled out)."
          },
          "stage": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "key",
              "name",
              "kind",
              "probability"
            ],
            "properties": {
              "key": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "open",
                  "won",
                  "lost"
                ]
              },
              "probability": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The chance of a sale from this stage, as a percentage."
              }
            }
          },
          "stage_entered_at": {
            "type": "string",
            "format": "date-time"
          },
          "owner_assigned": {
            "type": "boolean",
            "description": "Whether someone on your team owns it."
          },
          "score": {
            "type": "integer",
            "description": "How promising the lead is, from 0 to 100."
          },
          "campaign_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "first_touched_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When your team first contacted them."
          },
          "last_touched_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LeadEvent": {
        "type": "object",
        "description": "Something that happened to a lead.",
        "additionalProperties": false,
        "required": [
          "id",
          "event",
          "contact_id",
          "campaign_id",
          "occurred_at",
          "detail"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "event": {
            "type": "string",
            "description": "What happened, such as `lead.created`, `lead.stage_changed`,\n`lead.status_changed`, `lead.owner_assigned`, or an activity\nsuch as `activity.policy.bound`.\n"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "campaign_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          },
          "detail": {
            "type": "object",
            "description": "The change but not its content (such as `{ \"from\": \"new\", \"to\": \"quoted\" }`).",
            "additionalProperties": false,
            "properties": {
              "from": {},
              "to": {},
              "stage": {},
              "kind": {},
              "fields": {},
              "reason": {},
              "status": {},
              "channel": {},
              "occurred_at": {}
            }
          }
        }
      },
      "OutcomeInput": {
        "type": "object",
        "description": "One outcome to report.",
        "required": [
          "type",
          "occurred_at",
          "lead"
        ],
        "properties": {
          "event_id": {
            "type": "string",
            "description": "Your own id for this outcome. Strongly recommended, because it makes sending it again safe."
          },
          "type": {
            "type": "string",
            "description": "The outcome type's key, from [The outcomes you can send](/developers/api/reference/crm-outcomes#getOutcomeModel), such as `quoted`, `sold` or `cancelled`."
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it happened (ISO 8601)."
          },
          "lead": {
            "type": "object",
            "description": "Which lead it's about. Send `id`, or `external_id`, or set `match_on_details` and send `email` or `phone`.",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Subcontext's id for the lead (its `contact_id`)."
              },
              "external_id": {
                "type": "string",
                "description": "Your system's id for the lead."
              },
              "email": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              },
              "match_on_details": {
                "type": "boolean",
                "description": "Match by email or phone when there's no id. Only a single exact match counts."
              }
            }
          },
          "values": {
            "type": "object",
            "description": "The outcome's values, by measure key. Money in whole pence (`14940` is £149.40), percentages as percentages (`22.5`), counts as whole numbers.",
            "additionalProperties": {
              "type": [
                "number",
                "string"
              ]
            }
          },
          "currency": {
            "type": "string",
            "description": "Only `GBP`."
          },
          "deal_ref": {
            "type": "string",
            "description": "Your reference for the deal. A cancellation finds its sale by this."
          },
          "product": {
            "type": "string",
            "description": "Which of your products, by key, alias or name."
          },
          "reason": {
            "type": "string",
            "description": "For a cancellation, why."
          },
          "note": {
            "type": "string",
            "description": "A note for your team."
          }
        }
      },
      "Outcome": {
        "type": "object",
        "description": "An outcome recorded against a lead.",
        "additionalProperties": false,
        "required": [
          "id",
          "event_id",
          "type",
          "contact_id",
          "occurred_at",
          "source",
          "deal_ref",
          "product",
          "values",
          "missing_values",
          "currency",
          "reversed",
          "reversal_of"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "event_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The `event_id` it was sent with."
          },
          "type": {
            "type": "string"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          },
          "source": {
            "type": "string",
            "description": "How it was recorded, such as `api`, `upload` or `manual`."
          },
          "deal_ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "product": {
            "type": [
              "string",
              "null"
            ],
            "description": "The product's key."
          },
          "values": {
            "type": "object",
            "description": "Its values, by measure key. Money in whole pence, percentages as percentages, counts as whole numbers.",
            "additionalProperties": {
              "type": [
                "number",
                "null"
              ]
            }
          },
          "missing_values": {
            "type": "array",
            "description": "Required values it doesn't have yet.",
            "items": {
              "type": "string"
            }
          },
          "currency": {
            "type": [
              "string",
              "null"
            ]
          },
          "reversed": {
            "type": "boolean",
            "description": "Whether it has been reversed."
          },
          "reversal_of": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "For a reversal, the outcome it reverses."
          }
        }
      },
      "Membership": {
        "type": "object",
        "description": "A policyholder's membership of your loyalty programme.",
        "additionalProperties": false,
        "required": [
          "id",
          "programme_slug",
          "programme_name",
          "policy_number",
          "status",
          "external_member_ref",
          "current_tier_key",
          "cycle_points",
          "cycle_started_on",
          "cycle_ends_on"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Subcontext's id for the membership."
          },
          "programme_slug": {
            "type": "string"
          },
          "programme_name": {
            "type": "string"
          },
          "policy_number": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "suspended",
              "cancelled"
            ]
          },
          "external_member_ref": {
            "type": [
              "string",
              "null"
            ],
            "description": "Your reference for the member, once confirmed."
          },
          "current_tier_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "cycle_points": {
            "type": "integer",
            "description": "Points earned this cycle."
          },
          "cycle_started_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "cycle_ends_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          }
        }
      },
      "MembershipInput": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "cancelled"
            ],
            "description": "The new status."
          },
          "external_member_ref": {
            "type": "string",
            "description": "Your reference for the member. Required to confirm a pending enrolment."
          }
        }
      },
      "OutreachStream": {
        "type": "object",
        "description": "An outreach stream and its progress.",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "status",
          "archived_at",
          "kind",
          "purpose",
          "goal",
          "channels",
          "all_channels",
          "follow_up_after_days",
          "auto_send",
          "pace_per_hour",
          "message_mode",
          "from_name",
          "reply_email_template_key",
          "reply_email_template_id",
          "date_column",
          "date_field",
          "offset_days",
          "send_at_local_time",
          "schedule",
          "next_issue_at",
          "skip_if_unchanged",
          "issues_sent_count",
          "subscribed_count",
          "survey",
          "survey_answered_count",
          "awaiting_approval_count",
          "rows_count",
          "analysed_count",
          "skipped_count",
          "sent_count",
          "errored_count",
          "outcomes",
          "total_cost_pence",
          "cost_ceiling_pence",
          "budget_exceeded",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "`active` or `closed` (no new people; those in it carry on). `cancelled` (stopped for good) is only on streams cancelled before what's in progress could be cancelled on its own.",
            "enum": [
              "active",
              "cancelled",
              "closed"
            ]
          },
          "archived_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the stream was archived off the dashboard's streams list; null while it's on it. Archiving changes nothing else."
          },
          "kind": {
            "type": "string",
            "description": "Its shape: `mailshot` (one message, no link or follow-up), `conversation` (an opening message the agent follows through, with an optional link and one follow-up), `sequence` (a message then later steps, each a while after the one before, until the person engages), `reminder` (messages placed around a date each person has, like a renewal), `newsletter` (the same message to its subscribers on a schedule, each run an issue) or `survey` (one question, with at most one reminder, whose answers are recorded).",
            "enum": [
              "conversation",
              "sequence",
              "mailshot",
              "reminder",
              "newsletter",
              "survey"
            ]
          },
          "purpose": {
            "type": "string",
            "description": "What its messages are for, as consent sees it: `service`, `first_party_marketing` or `third_party_marketing`. Each person is checked against it as they join and as each message sends.",
            "enum": [
              "service",
              "first_party_marketing",
              "third_party_marketing"
            ]
          },
          "goal": {
            "type": "string",
            "description": "What the stream is for.",
            "enum": [
              "bookings",
              "sales",
              "engagement",
              "other"
            ]
          },
          "channels": {
            "type": "array",
            "description": "The channels it messages on, in order of preference.",
            "items": {
              "type": "string",
              "enum": [
                "whatsapp",
                "sms",
                "email"
              ]
            }
          },
          "all_channels": {
            "type": "boolean",
            "description": "Whether each person is messaged on every channel, rather than the first that reaches them."
          },
          "follow_up_after_days": {
            "type": "integer",
            "description": "Days before a follow-up to people who haven't replied (0 for none)."
          },
          "auto_send": {
            "type": "boolean",
            "description": "Whether messages go without a person approving each one."
          },
          "pace_per_hour": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The most messages sent an hour."
          },
          "message_mode": {
            "type": "string",
            "description": "Messages written for each person (`drafted`) or one fixed message (`fixed`).",
            "enum": [
              "drafted",
              "fixed"
            ]
          },
          "from_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The name its emails come from, when it sets its own (the address doesn't change); null sends them under the name of the agent, or of the team member it's written as."
          },
          "reply_email_template_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "The built-in email design (e.g. `plain`, `gmail`) its emails wear once the person has replied: the agent's answers and the team's. Null with a null `reply_email_template_id` keeps the outreach emails' own design."
          },
          "reply_email_template_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "One of the organisation's own email templates its emails wear once the person has replied, in place of a built-in one."
          },
          "date_column": {
            "type": [
              "string",
              "null"
            ],
            "description": "A reminder: the column of an uploaded list that holds each person's date."
          },
          "date_field": {
            "type": [
              "string",
              "null"
            ],
            "description": "A reminder: the lead field (its key) a workflow or the leads list reads each person's date from."
          },
          "offset_days": {
            "type": [
              "integer",
              "null"
            ],
            "description": "A reminder: the days from each person's date its first message is sent (negative before it, 0 on the day, positive after)."
          },
          "send_at_local_time": {
            "type": [
              "string",
              "null"
            ],
            "description": "A reminder or newsletter: the time of day (HH:MM, the organisation's time zone) its messages are sent."
          },
          "schedule": {
            "type": [
              "object",
              "null"
            ],
            "description": "A newsletter: when its issues go. `cadence` is `weekly` or `fortnightly` (with a `weekday`) or `monthly` (on a `day`, 1 to 31 or `last`, or a `week`, `first` to `fourth` or `last`, and a `weekday`); `starts_on` (YYYY-MM-DD) is the first day one may go."
          },
          "next_issue_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "A newsletter: when its next issue is due."
          },
          "skip_if_unchanged": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "A newsletter: whether an issue is skipped when the content it's built from hasn't changed since the last."
          },
          "issues_sent_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "A newsletter: how many issues have gone."
          },
          "subscribed_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "A newsletter: the people subscribed to it now."
          },
          "survey": {
            "type": [
              "object",
              "null"
            ],
            "description": "A survey: its `question`, the lead field its answers are kept in (`question_key`), the `answer_type` (`nps`, `rating`, `yes_no` or `text`) and any `follow_up_question` asked after a low score."
          },
          "survey_answered_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "A survey: how many people have answered."
          },
          "awaiting_approval_count": {
            "type": "integer",
            "description": "Messages waiting for a person to approve them."
          },
          "rows_count": {
            "type": "integer",
            "description": "People in the stream."
          },
          "analysed_count": {
            "type": "integer",
            "description": "People whose message has been prepared."
          },
          "skipped_count": {
            "type": "integer",
            "description": "People left out (no way to reach them, or no consent)."
          },
          "sent_count": {
            "type": "integer"
          },
          "errored_count": {
            "type": "integer"
          },
          "outcomes": {
            "type": "object",
            "description": "How many people replied, booked, started an application and bought.",
            "additionalProperties": false,
            "required": [
              "replied",
              "booked",
              "applications",
              "bound"
            ],
            "properties": {
              "replied": {
                "type": "integer"
              },
              "booked": {
                "type": "integer"
              },
              "applications": {
                "type": "integer"
              },
              "bound": {
                "type": "integer"
              }
            }
          },
          "total_cost_pence": {
            "type": "integer",
            "description": "What the stream's AI work has cost so far, in whole pence. It's metered in US dollars, so this is converted at today's exchange rate and rounded to the nearest penny."
          },
          "cost_ceiling_pence": {
            "type": "integer",
            "description": "The most it may cost, in whole pence (converted and rounded the same way). The stream stops when it's reached (`budget_exceeded`)."
          },
          "budget_exceeded": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  }
}