Contact lenses

Manage contact lenses

Creating a contact-lens subscription

Use the standard solicitation endpoint with a subscription_package cart item whose items array contains one contact_lens_subscription per eye. See Create the Subscription Solicitation for the surrounding flow (merchant, operator, personal data, webhook confirmation).

Endpoint /api/public/v1/subscriptions

Method POST

Swagger https://docs.sequra.com/update/reference/post_api-public-v1-subscriptions#/

Cart items

{
  "cart_items": [
    {
      "reference": "PKG-001",
      "name": "Contact lens package",
      "price_with_tax": 50000,
      "quantity": 1,
      "type": "subscription_package",
      "items": [
        {
          "reference": "CL-LEFT-001",
          "type": "contact_lens_subscription",
          "name": "Left contact lens",
          "price_with_tax": 25000,
          "subscription_price": 1000,
          "quantity": 1,
          "box_count": 4,
          "exchange_cycle": 12,
          "product_data": { "eye": "left" }
        },
        {
          "reference": "CL-RIGHT-001",
          "type": "contact_lens_subscription",
          "name": "Right contact lens",
          "price_with_tax": 25000,
          "subscription_price": 1000,
          "quantity": 1,
          "box_count": 4,
          "exchange_cycle": 12,
          "product_data": { "eye": "right" }
        }
      ]
    }
  ]
}

Send one contact_lens_subscription per eye. The typical case is two children — one for left, one for right — but you may send a single child with eye: "both" when the same lens is fitted on both eyes.

Parameters

ParameterTypeRequiredDescription
typestringyes"contact_lens_subscription" for each per-eye item nested inside the package.
box_countintegeryesBoxes the shopper is entitled to receive per subscription year for this eye. Must be ≥ 1.
exchange_cycleintegernoMonths between exchange windows. Defaults to 12. Pass 0 to disable the exchange window.
product_data.eyestringyes"left", "right", or "both".

The other fields (reference, name, price_with_tax, subscription_price, quantity) follow the same conventions as any subscription cart item.

Registering box deliveries

Endpoint /api/public/v1/subscriptions/:subscription_id/box_deliveries

Method POST

Swagger https://docs.sequra.com/update/reference/post_api-public-v1-subscriptions-id-box-deliveries#/

Payload

{
  "deliveries": [
    {
      "cart_item_reference_uuid": "1a8c9f30-…-left",
      "quantity": 1
    },
    {
      "cart_item_reference_uuid": "1a8c9f30-…-right",
      "quantity": 1
    }
  ]
}

Each entry references one contact-lens item by its reference_uuid (returned in the subscription response) and the boxes delivered in this call. A "both eyes" delivery is two entries — one per eye — even when the box totals match.

Parameters

ParameterTypeRequiredDescription
deliveriesarrayyesNon-empty list of per-item entries.
deliveries[].cart_item_reference_uuidstringyesThe reference_uuid of the contact_lens_subscription item being delivered.
deliveries[].quantityintegeryesBoxes delivered in this call. Must be ≥ 1.

Response

{
  "deliveries": [
    {
      "id": "06006609-…",
      "type": "contact_lens_subscription",
      "reference": "CL-LEFT-001",
      "reference_uuid": "1a8c9f30-…-left",
      "name": "Left contact lens",
      "quantity": 1,
      "box_count": 4,
      "delivered_boxes": 1,
      "remaining_boxes": 3,
      "price_with_tax":     { "value": 25000, "string": "250,00 €" },
      "total_with_tax":     { "value": 25000, "string": "250,00 €" },
      "subscription_price": { "value":  1000, "string":  "10,00 €" }
    }
  ]
}

The response includes a snapshot of every affected item after the call. delivered_boxes and remaining_boxes are scoped to the current subscription year (anchored on the subscription's activation date) and reset when the subscription enters its next year.

Idempotency

This endpoint is not idempotent. Two identical POSTs each succeed and delivered_boxes accumulates. The only safety net is the box_count cap: a request that would push delivered_boxes past box_count is rejected with 422. Deduplicate on the caller side if you need at-most-once semantics.

Error responses

HTTP statusReason
400Malformed payload — missing deliveries, empty array, missing per-entry fields, non-positive quantity.
401Missing or invalid HTTP Basic credentials, or the API account does not reference the subscription's merchant.
404Subscription not found.
409The subscription has no confirmed cart.
422The cart_item_reference_uuid is unknown, points to a non-contact-lens item, or quantity exceeds the eye's remaining capacity for the current subscription year.

For 422 over-delivery responses, the body includes the offending cart_item_reference_uuid and the boxes still remaining for that eye.

Reading delivery state

GET /api/public/v1/subscriptions/:id returns, for every contact-lens item nested inside a package, three counters:

  • box_count — entitled boxes per subscription year.
  • delivered_boxes — boxes registered so far in the current year.
  • remaining_boxesbox_count − delivered_boxes.
{
  "last_persisted_cart": {
    "cart_items": [
      {
        "type": "subscription_package",
        "items": [
          {
            "type": "contact_lens_subscription",
            "reference_uuid": "1a8c9f30-…-left",
            "product_data": { "eye": "left" },
            "box_count": 4,
            "delivered_boxes": 1,
            "remaining_boxes": 3
          },
          {
            "type": "contact_lens_subscription",
            "reference_uuid": "1a8c9f30-…-right",
            "product_data": { "eye": "right" },
            "box_count": 4,
            "delivered_boxes": 1,
            "remaining_boxes": 3
          }
        ]
      }
    ]
  }
}