{
  "openapi": "3.1.0",
  "info": {
    "title": "Cost+ Payment API",
    "version": "1.0.0",
    "description": "The Cost+ Payment Processing API. Use this API to create and manage orders, process payments, handle refunds, and manage payment links.\n\n**Base URL:** `https://api.costplus.online/v1`\n\n**Authentication:** HTTP Basic Auth — use your API key as the username with an empty password.\n"
  },
  "servers": [
    {
      "url": "https://api.costplus.online/v1",
      "description": "Production"
    },
    {
      "url": "https://api.nopayn.co.uk/v1",
      "description": "Legacy (NoPayn)"
    }
  ],
  "security": [
    {
      "basicAuth": []
    }
  ],
  "tags": [
    {
      "name": "Orders",
      "description": "Create and manage payment orders"
    },
    {
      "name": "Payment Links",
      "description": "Create and manage reusable payment links"
    },
    {
      "name": "Search",
      "description": "Search across orders"
    },
    {
      "name": "Self Service",
      "description": "Account and project management"
    },
    {
      "name": "Webhooks",
      "description": "Webhook event specifications"
    }
  ],
  "paths": {
    "/orders": {
      "get": {
        "operationId": "listOrders",
        "summary": "List orders by date range",
        "description": "Retrieve a collection of orders created within the specified period.",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  'https://api.costplus.online/v1/orders/?created_since=2026-01-01T00:00:00Z&created_until=2026-02-01T00:00:00Z'\n"
          }
        ],
        "parameters": [
          {
            "name": "created_since",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Start of the period (ISO 8601)"
          },
          {
            "name": "created_until",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "End of the period (ISO 8601)"
          }
        ],
        "responses": {
          "200": {
            "description": "A collection of orders",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Order"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "operationId": "createOrder",
        "summary": "Create a new order",
        "description": "Create a new payment order.\n\nThe response shape depends on the request body:\n- If you send a `transactions` array, each transaction object in the response contains its own `payment_url`. Redirect the customer to that URL.\n- If you omit `transactions`, the order has a top-level `order_url` instead — the hosted page lets the customer pick from all enabled payment methods.\n\nSee the [Hosted Payment Page guide](/docs/guides/hosted-payment-page) for both flows side by side.\n",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X POST https://api.costplus.online/v1/orders/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"amount\": 1295,\n    \"currency\": \"EUR\",\n    \"merchant_order_id\": \"ORDER-1\",\n    \"description\": \"Test order\",\n    \"return_url\": \"https://example.com/return\",\n    \"failure_url\": \"https://example.com/cancel\",\n    \"webhook_url\": \"https://example.com/webhook\",\n    \"transactions\": [{ \"payment_method\": \"credit-card\" }]\n  }'\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Order"
              },
              "example": {
                "currency": "EUR",
                "amount": 1295,
                "merchant_order_id": "my-order-id-1",
                "description": "My amazing order",
                "return_url": "https://www.example.com",
                "webhook_url": "https://www.example.com/webhook",
                "transactions": [
                  {
                    "payment_method": "credit-card"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "with-transactions": {
                    "summary": "With a `transactions` array — `payment_url` inside each transaction",
                    "value": {
                      "id": "4851e31c-4137-4e91-95ef-1df945ee76a2",
                      "merchant_order_id": "my-order-id-1",
                      "status": "new",
                      "currency": "EUR",
                      "amount": 1295,
                      "description": "My amazing order",
                      "created": "2026-01-15T12:00:05.433502+00:00",
                      "modified": "2026-01-15T12:00:05.553125+00:00",
                      "expiration_period": "PT1H",
                      "return_url": "https://www.example.com",
                      "webhook_url": "https://www.example.com/webhook",
                      "transactions": [
                        {
                          "id": "d291f03f-a406-428a-967a-4895a46e03fd",
                          "payment_method": "credit-card",
                          "status": "new",
                          "amount": 1295,
                          "currency": "EUR",
                          "channel": "ecom",
                          "credit_debit": "credit",
                          "is_capturable": false,
                          "expiration_period": "PT30M",
                          "payment_url": "https://api.costplus.online/pay/4851e31c.../select-payment-method/credit-card/d291f03f.../",
                          "payment_method_details": {}
                        }
                      ]
                    }
                  },
                  "without-transactions": {
                    "summary": "Without `transactions` — top-level `order_url`",
                    "value": {
                      "id": "43114fde-da30-4115-8004-b7f808f9b25c",
                      "merchant_order_id": "my-order-id-1",
                      "status": "new",
                      "currency": "EUR",
                      "amount": 1295,
                      "description": "My amazing order",
                      "created": "2026-01-15T12:00:05.433502+00:00",
                      "modified": "2026-01-15T12:00:05.553125+00:00",
                      "expiration_period": "PT1H",
                      "return_url": "https://www.example.com",
                      "webhook_url": "https://www.example.com/webhook",
                      "order_url": "https://api.costplus.online/pay/43114fde.../select-payment-method/"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/orders/{id}": {
      "get": {
        "operationId": "getOrder",
        "summary": "Get a single order",
        "description": "Retrieve the full details of an order including its transactions.\n\nUse `?fields[]=amount_details` to include a financial breakdown (captured, capturable, refunded, refundable, voided, voidable amounts) — useful for partial capture and refund scenarios.\n",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  'https://api.costplus.online/v1/orders/4851e31c-4137-4e91-95ef-1df945ee76a2/?fields[]=amount_details'\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          },
          {
            "name": "fields[]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "amount_details",
                "order_line_details"
              ]
            },
            "description": "Request extra fields: `amount_details` (financial breakdown) or `order_line_details` (per-line capture/refund status)"
          }
        ],
        "responses": {
          "200": {
            "description": "The order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "example": {
                  "id": "4851e31c-4137-4e91-95ef-1df945ee76a2",
                  "merchant_order_id": "my-order-id-1",
                  "status": "completed",
                  "currency": "EUR",
                  "amount": 1295,
                  "description": "My amazing order",
                  "created": "2026-01-15T12:00:05.433502+00:00",
                  "modified": "2026-01-15T12:02:30.123456+00:00",
                  "completed": "2026-01-15T12:02:30.123456+00:00",
                  "expiration_period": "PT1H",
                  "return_url": "https://www.example.com",
                  "webhook_url": "https://www.example.com/webhook",
                  "transactions": [
                    {
                      "id": "d291f03f-a406-428a-967a-4895a46e03fd",
                      "payment_method": "credit-card",
                      "status": "completed",
                      "amount": 1295,
                      "currency": "EUR",
                      "channel": "ecom",
                      "credit_debit": "credit",
                      "is_capturable": false,
                      "payment_method_details": {
                        "truncated_pan": "1111",
                        "card_expiry": "122028"
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "put": {
        "operationId": "updateOrder",
        "summary": "Update an order",
        "description": "Update the properties of an existing order.",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X PUT https://api.costplus.online/v1/orders/4851e31c-4137-4e91-95ef-1df945ee76a2/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{ \"description\": \"Updated description\" }'\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Order"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "delete": {
        "operationId": "cancelOrder",
        "summary": "Cancel an order",
        "description": "Cancel an order if it has not been completed yet.",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X DELETE https://api.costplus.online/v1/orders/4851e31c-4137-4e91-95ef-1df945ee76a2/\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          }
        ],
        "responses": {
          "200": {
            "description": "The cancelled order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/orders/{id}/refunds": {
      "get": {
        "operationId": "listRefunds",
        "summary": "List refunds for an order",
        "description": "Retrieve all refund orders associated with the specified order.",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  https://api.costplus.online/v1/orders/4851e31c-4137-4e91-95ef-1df945ee76a2/refunds/\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          }
        ],
        "responses": {
          "200": {
            "description": "A collection of refund orders",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Order"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "operationId": "createRefund",
        "summary": "Create a refund",
        "description": "Create a full or partial refund for an order.",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X POST https://api.costplus.online/v1/orders/4851e31c-4137-4e91-95ef-1df945ee76a2/refunds/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{ \"amount\": 500, \"description\": \"Refund for damaged item\" }'\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Refund"
              },
              "example": {
                "amount": 500,
                "description": "Refund for damaged item",
                "merchant_order_id": "refund-001"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The order with the refund applied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/orders/{id}/transactions/{transaction_id}/captures/orderlines": {
      "post": {
        "operationId": "captureByOrderLine",
        "summary": "Capture by order line",
        "description": "Capture specific order lines from an authorized transaction.",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X POST 'https://api.costplus.online/v1/orders/{id}/transactions/{transaction_id}/captures/orderlines/' \\\n  -H 'Content-Type: application/json' \\\n  -H 'If-Match: <etag-from-GET-order>' \\\n  -d '{ \"order_lines\": [ { \"id\": \"line-1\", \"quantity\": 1 } ] }'\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          },
          {
            "$ref": "#/components/parameters/TransactionId"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaptureOrderLines"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          }
        }
      }
    },
    "/orders/{id}/transactions/{transaction_id}/captures/amount": {
      "post": {
        "operationId": "captureByAmount",
        "summary": "Capture by amount",
        "description": "Capture a specific amount from an authorized transaction.",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X POST 'https://api.costplus.online/v1/orders/{id}/transactions/{transaction_id}/captures/amount/' \\\n  -H 'Content-Type: application/json' \\\n  -H 'If-Match: <etag-from-GET-order>' \\\n  -d '{ \"amount\": 2500, \"description\": \"Partial capture\" }'\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          },
          {
            "$ref": "#/components/parameters/TransactionId"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaptureAmount"
              },
              "example": {
                "description": "Partial capture",
                "amount": 2500
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          }
        }
      }
    },
    "/orders/{id}/transactions/{transaction_id}/voids/orderlines": {
      "post": {
        "operationId": "voidByOrderLine",
        "summary": "Void by order line",
        "description": "Void specific order lines from an authorized transaction.",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X POST 'https://api.costplus.online/v1/orders/{id}/transactions/{transaction_id}/voids/orderlines/' \\\n  -H 'Content-Type: application/json' \\\n  -H 'If-Match: <etag-from-GET-order>' \\\n  -d '{ \"order_lines\": [ { \"id\": \"line-1\", \"quantity\": 1 } ] }'\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          },
          {
            "$ref": "#/components/parameters/TransactionId"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoidOrderLines"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          }
        }
      }
    },
    "/orders/{id}/transactions/{transaction_id}/voids/amount": {
      "post": {
        "operationId": "voidByAmount",
        "summary": "Void by amount",
        "description": "Void a specific amount from an authorized transaction.",
        "tags": [
          "Orders"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X POST 'https://api.costplus.online/v1/orders/{id}/transactions/{transaction_id}/voids/amount/' \\\n  -H 'Content-Type: application/json' \\\n  -H 'If-Match: <etag-from-GET-order>' \\\n  -d '{ \"amount\": 1500, \"description\": \"Partial void\" }'\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          },
          {
            "$ref": "#/components/parameters/TransactionId"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoidAmount"
              },
              "example": {
                "description": "Partial void",
                "amount": 1500
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          }
        }
      }
    },
    "/paymentlinks/": {
      "post": {
        "operationId": "createPaymentLink",
        "summary": "Create a payment link",
        "description": "Create a new reusable payment link. The response includes a `payment_url` to share with the customer.\nThe customer can attempt payment multiple times (up to 25 attempts) until the link expires or payment succeeds.\n",
        "tags": [
          "Payment Links"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X POST https://api.costplus.online/v1/paymentlinks/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{ \"merchant_order_id\": \"invoice-1234\", \"amount\": 995, \"currency\": \"EUR\", \"description\": \"Invoice #1234\" }'\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PaymentLink"
              },
              "example": {
                "merchant_order_id": "invoice-1234",
                "amount": 995,
                "currency": "EUR",
                "description": "Invoice #1234"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created payment link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLink"
                },
                "example": {
                  "id": "e6eecc6a-47c5-4948-bcc0-d8b73f5c55a1",
                  "merchant_order_id": "invoice-1234",
                  "amount": 995,
                  "currency": "EUR",
                  "description": "Invoice #1234",
                  "expiration_period": "P30D",
                  "payment_url": "https://api.costplus.online/paymentlinks/e6eecc6a-47c5-4948-bcc0-d8b73f5c55a1/",
                  "status": "new",
                  "reason": "Payment Link was created, not yet visited",
                  "orders": {},
                  "created": "2026-01-15T12:00:00.000000Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/paymentlinks/{id}": {
      "get": {
        "operationId": "getPaymentLink",
        "summary": "Get a payment link",
        "description": "Retrieve the details of a payment link, including all associated orders grouped by status.",
        "tags": [
          "Payment Links"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  https://api.costplus.online/v1/paymentlinks/e6eecc6a-47c5-4948-bcc0-d8b73f5c55a1/\n"
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The payment link ID (returned when the link was created)"
          }
        ],
        "responses": {
          "200": {
            "description": "The payment link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLink"
                },
                "example": {
                  "id": "e6eecc6a-47c5-4948-bcc0-d8b73f5c55a1",
                  "merchant_order_id": "invoice-1234",
                  "amount": 995,
                  "currency": "EUR",
                  "description": "Invoice #1234",
                  "expiration_period": "P30D",
                  "payment_url": "https://api.costplus.online/paymentlinks/e6eecc6a-47c5-4948-bcc0-d8b73f5c55a1/",
                  "status": "completed",
                  "reason": "Completed",
                  "completed": "2026-01-15T12:05:30.123456+00:00",
                  "completed_order_id": "3bb663cc-2a20-400d-8bf6-18d9695d0c66",
                  "orders": {
                    "error": [
                      "0d79014c-0aaa-4fd6-87c5-c8cfa5f5ac69"
                    ],
                    "completed": [
                      "3bb663cc-2a20-400d-8bf6-18d9695d0c66"
                    ]
                  },
                  "created": "2026-01-15T12:00:00.000000Z",
                  "modified": "2026-01-15T12:05:35.654321Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/search/orders": {
      "post": {
        "operationId": "searchOrders",
        "summary": "Search orders",
        "description": "Search across orders using free-form criteria.",
        "tags": [
          "Search"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  -X POST https://api.costplus.online/v1/search/orders/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{ \"merchant_order_id\": \"ORDER-1\" }'\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "hits": {
                      "type": "integer",
                      "readOnly": true,
                      "description": "Total number of matching orders"
                    },
                    "orders": {
                      "type": "array",
                      "uniqueItems": true,
                      "items": {
                        "$ref": "#/components/schemas/SearchOrder"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/merchants/self/projects/self/currencies": {
      "get": {
        "operationId": "getSupportedCurrencies",
        "summary": "Get supported currencies",
        "description": "List supported currencies for each available payment method in your project.",
        "tags": [
          "Self Service"
        ],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -u YOUR_API_KEY: \\\n  https://api.costplus.online/v1/merchants/self/projects/self/currencies/\n"
          }
        ],
        "responses": {
          "200": {
            "description": "Supported currencies per payment method",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment_methods": {
                      "type": "object",
                      "description": "Keyed by payment method name",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "currencies": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "ISO 4217 currency codes"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/tokens/": {
      "post": {
        "operationId": "createToken",
        "summary": "Tokenize card details",
        "description": "Exchange a card PAN and setup token for a vault token. This endpoint is used as part of the custom card entry form flow — after creating an order with `setup_token: true`, use this endpoint to securely vault the card details.\n\n**Note:** This endpoint is authenticated via the `setup_token`, not your API key. No `Authorization` header is required.\n",
        "tags": [
          "Orders"
        ],
        "security": [],
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -X POST https://api.costplus.online/v1/tokens/ \\\n  -H 'Content-Type: application/json' \\\n  -d '{ \"pan\": \"4111111111111111\", \"expiry_date\": \"1228\", \"setup_token\": \"SETUP_TOKEN_FROM_ORDER\" }'\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "pan",
                  "expiry_date",
                  "setup_token"
                ],
                "properties": {
                  "pan": {
                    "type": "string",
                    "description": "The full card number (PAN)",
                    "example": "4111111111111111"
                  },
                  "expiry_date": {
                    "type": "string",
                    "description": "Card expiry date in MMYY format",
                    "example": "1228"
                  },
                  "setup_token": {
                    "type": "string",
                    "description": "The setup token received from the order creation response"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card successfully tokenized",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "vault_token": {
                      "type": "string",
                      "description": "Token representing the stored card PAN, used for subsequent payments"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (bad PAN, expired setup token, etc.)"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "basicAuth": {
        "type": "http",
        "scheme": "basic",
        "description": "Use your API key as the username and leave the password empty.\nEncode as Base64: `{api_key}:` (note the trailing colon).\n"
      }
    },
    "parameters": {
      "OrderId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Order identifier"
      },
      "TransactionId": {
        "name": "transaction_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Transaction identifier"
      },
      "IfMatch": {
        "name": "if-match",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "ETag for optimistic locking. Only process if the order version matches."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Invalid or missing API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "No authorization for the requested resource",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PreconditionFailed": {
        "description": "ETag version mismatch — the order was modified since last fetched",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Order": {
        "type": "object",
        "required": [
          "currency",
          "amount"
        ],
        "properties": {
          "id": {
            "type": "string",
            "readOnly": true,
            "description": "Order identifier"
          },
          "project_id": {
            "type": "string",
            "readOnly": true,
            "description": "Project identifier"
          },
          "merchant_id": {
            "type": "string",
            "readOnly": true,
            "description": "Merchant identifier used to create the order"
          },
          "order_url": {
            "type": "string",
            "readOnly": true,
            "description": "The order URL if available"
          },
          "refund_of_order_id": {
            "type": "string",
            "readOnly": true,
            "description": "Order ID of the original order, if this is a refund"
          },
          "refund_orders": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "readOnly": true,
            "description": "Order IDs of related refund orders"
          },
          "refunded_amount": {
            "type": "integer",
            "readOnly": true,
            "description": "Amount refunded on this order"
          },
          "chargeback_of_order_id": {
            "type": "string",
            "readOnly": true,
            "description": "Order ID of the original order, if this is a chargeback"
          },
          "chargeback_orders": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "readOnly": true,
            "description": "Order IDs of related chargeback orders"
          },
          "reversal_of_order_id": {
            "type": "string",
            "readOnly": true,
            "description": "Order ID of the original order, if this is a reversal"
          },
          "reversal_orders": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "readOnly": true,
            "description": "Order IDs of related reversal orders"
          },
          "related_order_id": {
            "type": "string",
            "readOnly": true,
            "description": "Order ID of the original order"
          },
          "related_orders": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "readOnly": true,
            "description": "Order IDs of related orders"
          },
          "related_payment_link_id": {
            "type": "string",
            "readOnly": true,
            "description": "ID of the related payment link"
          },
          "merchant_order_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Merchant's internal order identifier"
          },
          "merchant_bulk_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Merchant bulk ID (for grouping transactions for payouts)"
          },
          "merchant_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Merchant name (for payouts)"
          },
          "merchant_iban": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,34}$",
            "description": "Merchant IBAN (for payouts)"
          },
          "merchant_bic": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$",
            "description": "Merchant BIC (for payouts)"
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Creation timestamp (ISO 8601)"
          },
          "modified": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "readOnly": true,
            "description": "Last modified timestamp (ISO 8601)"
          },
          "completed": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "readOnly": true,
            "description": "Completion timestamp (ISO 8601)"
          },
          "expiration_period": {
            "type": [
              "string",
              "null"
            ],
            "description": "Order expiration interval (ISO 8601 duration, e.g. PT30M)"
          },
          "capture_mode": {
            "type": "string",
            "enum": [
              "manual",
              "delayed"
            ],
            "description": "Capture mode. `delayed` requires `expiration_period`."
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code",
            "enum": [
              "AED",
              "AFN",
              "ANG",
              "ARS",
              "AUD",
              "AWG",
              "AZN",
              "BBD",
              "BDT",
              "BGN",
              "BHD",
              "BMD",
              "BND",
              "BOB",
              "BRL",
              "BSD",
              "BZD",
              "CAD",
              "CHF",
              "CLP",
              "CNY",
              "COP",
              "CRC",
              "CZK",
              "DKK",
              "DOP",
              "DZD",
              "EGP",
              "EUR",
              "FJD",
              "GBP",
              "GTQ",
              "GYD",
              "HKD",
              "HUF",
              "IDR",
              "ILS",
              "INR",
              "IQD",
              "ISK",
              "JMD",
              "JOD",
              "JPY",
              "KES",
              "KRW",
              "KWD",
              "KYD",
              "KZT",
              "LBP",
              "LKR",
              "MAD",
              "MDL",
              "MOP",
              "MXN",
              "MYR",
              "NGN",
              "NOK",
              "NPR",
              "NZD",
              "OMR",
              "PEN",
              "PHP",
              "PKR",
              "PLN",
              "PYG",
              "QAR",
              "RON",
              "SAR",
              "SCR",
              "SEK",
              "SGD",
              "SRD",
              "THB",
              "TND",
              "TRY",
              "TWD",
              "TZS",
              "UAH",
              "UGX",
              "USD",
              "UYU",
              "VND",
              "XCD",
              "XOF",
              "ZAR",
              "EEK",
              "LTL"
            ]
          },
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Order amount in minor units (e.g. cents), including VAT"
          },
          "description": {
            "type": "string",
            "description": "Order description"
          },
          "status": {
            "type": "string",
            "readOnly": true,
            "enum": [
              "new",
              "processing",
              "error",
              "completed",
              "cancelled",
              "expired"
            ],
            "description": "Current order status"
          },
          "flags": {
            "type": "array",
            "readOnly": true,
            "items": {
              "type": "string",
              "enum": [
                "is-test",
                "has-refunds",
                "is-refund",
                "has-chargebacks",
                "is-chargeback",
                "has-reversals",
                "is-reversal",
                "has-related-orders",
                "is-related-order",
                "from-payment-link"
              ]
            },
            "description": "Order flags"
          },
          "locale": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z]{2}([\\-_][a-zA-Z]{2})?$",
            "description": "Language for the hosted payment page. Supported: `en-GB`, `de-DE`, `nl-NL`, `nl-BE`, `fr-BE`, `sv-SE`, `no-NO`, `da-DK`"
          },
          "payment_methods": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "afterpay",
                "amex",
                "apple-pay",
                "bancontact",
                "bank-transfer",
                "credit-card",
                "giropay",
                "google-pay",
                "ideal",
                "klarna-direct-debit",
                "klarna-pay-later",
                "klarna-pay-now",
                "mobilepay",
                "payconiq",
                "paypal",
                "sepa-direct-debit",
                "sofort",
                "swish",
                "viacash",
                "billink",
                "anyday-split",
                "vipps-mobilepay"
              ]
            },
            "description": "Filter available payment methods for this order. Omit to show all enabled methods, or pass a single value to restrict to one method. To offer multiple specific methods, use the `transactions` array instead (one entry per method)."
          },
          "transactions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Transaction"
            },
            "description": "Collection of transactions"
          },
          "return_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "URL to redirect the customer after a successful or non-failure payment. Acts as the default redirect for all statuses when `failure_url` is not provided."
          },
          "failure_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "URL to redirect the customer when the order status is `cancelled`, `expired`, or `error`. Only used when both `return_url` and `failure_url` are provided."
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "URL for status change notifications"
          },
          "order_lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderLine"
            },
            "description": "Order line items"
          },
          "customer": {
            "$ref": "#/components/schemas/Customer"
          },
          "client": {
            "$ref": "#/components/schemas/Client"
          },
          "extra": {
            "type": "object",
            "description": "Free-form data stored with the order"
          }
        }
      },
      "Transaction": {
        "type": "object",
        "required": [
          "payment_method"
        ],
        "properties": {
          "id": {
            "type": "string",
            "readOnly": true,
            "description": "Transaction identifier"
          },
          "project_id": {
            "type": "string",
            "readOnly": true,
            "description": "Project identifier"
          },
          "merchant_id": {
            "type": "string",
            "readOnly": true,
            "description": "Merchant identifier"
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Creation timestamp"
          },
          "modified": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "readOnly": true,
            "description": "Last modified timestamp"
          },
          "completed": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "readOnly": true,
            "description": "Completion timestamp"
          },
          "expiration_period": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expiration interval (ISO 8601)"
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code"
          },
          "amount": {
            "type": "integer",
            "format": "int64",
            "minimum": 1,
            "maximum": 999999999999,
            "description": "Transaction amount in minor units"
          },
          "balance": {
            "type": "string",
            "readOnly": true,
            "enum": [
              "internal",
              "external",
              "test"
            ],
            "description": "Balance type"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Transaction description"
          },
          "product_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Product type"
          },
          "credit_debit": {
            "type": "string",
            "readOnly": true,
            "enum": [
              "credit",
              "debit"
            ],
            "description": "Whether this is a credit or debit"
          },
          "outcomes": {
            "type": "object",
            "readOnly": true,
            "description": "Transaction outcome information",
            "properties": {
              "fraud_prevention": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "accepted",
                      "declined",
                      "error"
                    ]
                  },
                  "score": {
                    "type": "number"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "error_description": {
                    "type": "string"
                  }
                }
              },
              "processing": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "accepted",
                      "declined",
                      "soft_declined",
                      "error"
                    ]
                  },
                  "response_code": {
                    "type": "string"
                  },
                  "response_code_description": {
                    "type": "string"
                  },
                  "merchant_advice_code": {
                    "type": "string"
                  },
                  "error_description": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "payment_method": {
            "type": "string",
            "enum": [
              "afterpay",
              "amex",
              "apple-pay",
              "bancontact",
              "bank-transfer",
              "credit-card",
              "credit-card-oct",
              "giropay",
              "google-pay",
              "ideal",
              "klarna-direct-debit",
              "klarna-pay-later",
              "klarna-pay-now",
              "mobilepay",
              "payconiq",
              "paypal",
              "sepa-direct-debit",
              "sofort",
              "swish",
              "viacash",
              "billink",
              "anyday-split",
              "vipps-mobilepay"
            ],
            "description": "Payment method. For refunds, `-refund` is appended (e.g. `credit-card-refund`)"
          },
          "payment_method_brand": {
            "type": "string",
            "description": "Payment method brand (e.g. Visa, Mastercard)"
          },
          "payment_method_details": {
            "$ref": "#/components/schemas/CreditCardDetails"
          },
          "payment_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "readOnly": true,
            "description": "URL to redirect the customer to for payment"
          },
          "status": {
            "type": "string",
            "readOnly": true,
            "enum": [
              "new",
              "pending",
              "processing",
              "accepted",
              "captured",
              "completed",
              "cancelled",
              "error",
              "expired"
            ],
            "description": "Current transaction status"
          },
          "is_capturable": {
            "type": "boolean",
            "readOnly": true,
            "description": "Whether the transaction can be captured"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "readOnly": true,
            "description": "Status reason (merchant-facing)"
          },
          "customer_message": {
            "type": [
              "string",
              "null"
            ],
            "readOnly": true,
            "description": "Status description (customer-facing)"
          },
          "msc_currency": {
            "type": "string",
            "const": "EUR",
            "readOnly": true,
            "description": "Merchant Service Charge currency"
          },
          "msc_amount": {
            "type": "integer",
            "minimum": 0,
            "readOnly": true,
            "description": "Merchant Service Charge amount"
          },
          "msc_calculation_type": {
            "type": "string",
            "enum": [
              "blended",
              "plus"
            ],
            "readOnly": true,
            "description": "MSC calculation method"
          },
          "icf_currency": {
            "type": "string",
            "const": "EUR",
            "readOnly": true,
            "description": "Interchange Fee currency"
          },
          "icf_amount": {
            "type": "integer",
            "minimum": 0,
            "readOnly": true,
            "description": "Interchange Fee amount"
          },
          "icp_currency": {
            "type": "string",
            "const": "EUR",
            "readOnly": true,
            "description": "Interchange Plus currency"
          },
          "icp_amount": {
            "type": "integer",
            "minimum": 0,
            "readOnly": true,
            "description": "Interchange Plus amount"
          },
          "payout_batch_id": {
            "type": "string",
            "readOnly": true,
            "description": "Payout batch identifier"
          }
        }
      },
      "CreditCardDetails": {
        "type": "object",
        "description": "Credit card specific details",
        "properties": {
          "datetime_local": {
            "type": "string",
            "format": "date-time",
            "description": "Consumer's local date & time"
          },
          "attempt_3dsecure": {
            "type": "boolean",
            "description": "Whether 3D-Secure should be attempted"
          },
          "require_3dsecure": {
            "type": "boolean",
            "description": "Whether 3D-Secure is required"
          },
          "setup_token": {
            "type": "string",
            "readOnly": true,
            "description": "Auth token for exchanging PAN for a vault token"
          },
          "vault_token": {
            "type": "string",
            "description": "Token representing the stored card PAN"
          },
          "cvc": {
            "type": "string",
            "description": "Card CVC/CVV value"
          },
          "one_click_type": {
            "type": "string",
            "enum": [
              "first",
              "one-click"
            ],
            "description": "One-click payment type"
          },
          "recurring_type": {
            "type": "string",
            "enum": [
              "first",
              "recurring"
            ],
            "description": "Recurring payment type"
          },
          "schedule_type": {
            "type": "string",
            "enum": [
              "scheduled",
              "unscheduled"
            ],
            "description": "Recurring schedule type"
          },
          "truncated_pan": {
            "type": "string",
            "readOnly": true,
            "description": "Last 4 digits of card number"
          },
          "card_expiry": {
            "type": "string",
            "readOnly": true,
            "description": "Card expiry (MMYYYY format)"
          },
          "cardholder_name": {
            "type": "string",
            "readOnly": true,
            "description": "Cardholder name"
          },
          "response_code": {
            "type": "string",
            "readOnly": true,
            "description": "Response code (ISO 8583 Field 39)"
          },
          "first_authorised_transaction_id": {
            "type": "string",
            "readOnly": true,
            "description": "Transaction ID of the first authorization"
          }
        }
      },
      "OrderLine": {
        "type": "object",
        "required": [
          "merchant_order_line_id",
          "name",
          "currency",
          "amount",
          "quantity",
          "vat_percentage"
        ],
        "properties": {
          "id": {
            "type": "string",
            "readOnly": true,
            "description": "Order line identifier"
          },
          "type": {
            "type": "string",
            "enum": [
              "physical",
              "discount",
              "shipping_fee",
              "sales_tax",
              "digital",
              "gift_card",
              "store_credit",
              "surcharge"
            ],
            "description": "Order line type"
          },
          "ean": {
            "type": "string",
            "description": "International Article Number (EAN)"
          },
          "merchant_order_line_id": {
            "type": "string",
            "description": "Merchant's internal order line identifier"
          },
          "name": {
            "type": "string",
            "description": "Item name / short description"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Item product page URL"
          },
          "image_url": {
            "type": "string",
            "format": "uri",
            "description": "Item image URL"
          },
          "currency": {
            "type": "string",
            "const": "EUR",
            "description": "Currency (currently EUR only)"
          },
          "amount": {
            "type": "integer",
            "description": "Amount per item in minor units (including VAT)"
          },
          "quantity": {
            "type": "integer",
            "description": "Quantity of items"
          },
          "discount_rate": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "description": "Discount percentage x100 (e.g. 11.57% = 1157)"
          },
          "vat_percentage": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "description": "Tax rate percentage x100 (e.g. 25% = 2500)"
          }
        }
      },
      "OrderLineReference": {
        "type": "object",
        "required": [
          "merchant_order_line_id",
          "quantity"
        ],
        "properties": {
          "merchant_order_line_id": {
            "type": "string",
            "description": "Merchant's order line identifier"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "description": "Number of items"
          }
        }
      },
      "Refund": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Refund amount in minor units"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Refund description"
          },
          "merchant_order_id": {
            "type": "string",
            "description": "Merchant's refund reference"
          },
          "order_lines": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/OrderLineReference"
            },
            "description": "Order lines to refund"
          }
        }
      },
      "CaptureOrderLines": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "description": "Capture description"
          },
          "order_line": {
            "$ref": "#/components/schemas/OrderLineReference"
          }
        }
      },
      "CaptureAmount": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "description": "Capture description"
          },
          "amount": {
            "type": "integer",
            "description": "Amount to capture in minor units"
          }
        }
      },
      "VoidOrderLines": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "description": "Void description"
          },
          "order_line": {
            "$ref": "#/components/schemas/OrderLineReference"
          }
        }
      },
      "VoidAmount": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "description": "Void description"
          },
          "amount": {
            "type": "integer",
            "description": "Amount to void in minor units"
          }
        }
      },
      "Customer": {
        "type": "object",
        "description": "Customer details",
        "properties": {
          "user_agent": {
            "type": [
              "string",
              "null"
            ],
            "description": "HTTP user agent"
          },
          "merchant_customer_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Merchant's internal customer ID"
          },
          "email_address": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "description": "Email address"
          },
          "first_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "First name"
          },
          "last_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Last name"
          },
          "address_type": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "customer",
              "delivery",
              "billing"
            ],
            "description": "Address type"
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Street address"
          },
          "postal_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Postal code"
          },
          "housenumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "House number"
          },
          "country": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z]{2}$",
            "description": "ISO 3166-1 alpha-2 country code"
          },
          "locale": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-zA-Z]{2}(_[a-zA-Z]{2})?$",
            "description": "POSIX locale"
          },
          "phone_numbers": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Phone numbers"
          },
          "ip_address": {
            "type": "string",
            "format": "ipv4",
            "description": "Customer's IP address"
          },
          "gender": {
            "type": "string",
            "enum": [
              "male",
              "female",
              "other"
            ],
            "description": "Gender"
          },
          "birthdate": {
            "type": "string",
            "format": "date-time",
            "description": "Birth date"
          },
          "additional_addresses": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object"
            },
            "description": "Additional addresses"
          }
        }
      },
      "Client": {
        "type": "object",
        "description": "Client integration details",
        "properties": {
          "user_agent": {
            "type": [
              "string",
              "null"
            ],
            "description": "HTTP user agent"
          },
          "platform_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform name (e.g. Magento Community Edition)"
          },
          "platform_version": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform version (e.g. 1.9.2.2)"
          },
          "plugin_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Plugin name (e.g. costplus-magento)"
          },
          "plugin_version": {
            "type": [
              "string",
              "null"
            ],
            "description": "Plugin version (e.g. 1.0.0)"
          }
        }
      },
      "PaymentLink": {
        "type": "object",
        "required": [
          "merchant_order_id",
          "amount",
          "currency"
        ],
        "properties": {
          "id": {
            "type": "string",
            "readOnly": true,
            "description": "Payment link identifier"
          },
          "merchant_order_id": {
            "type": "string",
            "description": "Merchant's internal order ID"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Payment link description"
          },
          "amount": {
            "type": "integer",
            "minimum": 1,
            "description": "Amount in minor units (including VAT)"
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code"
          },
          "expiration_period": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expiration interval (ISO 8601 duration)"
          },
          "payment_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "readOnly": true,
            "description": "Payment URL to share with customer"
          },
          "payment_methods": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "afterpay",
                "amex",
                "apple-pay",
                "bancontact",
                "bank-transfer",
                "credit-card",
                "giropay",
                "google-pay",
                "ideal",
                "klarna-direct-debit",
                "klarna-pay-later",
                "klarna-pay-now",
                "mobilepay",
                "payconiq",
                "paypal",
                "sepa-direct-debit",
                "sofort",
                "swish",
                "viacash",
                "billink",
                "anyday-split",
                "vipps-mobilepay"
              ]
            },
            "description": "Limit available payment methods for this payment link. Supports multiple values."
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Creation timestamp"
          },
          "modified": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Last modified timestamp"
          },
          "completed_order_id": {
            "type": "string",
            "readOnly": true,
            "description": "ID of the completed order"
          },
          "status": {
            "type": "string",
            "readOnly": true,
            "enum": [
              "new",
              "processing",
              "completed",
              "expired",
              "all_unsuccessful"
            ],
            "description": "Payment link status"
          },
          "reason": {
            "type": "string",
            "readOnly": true,
            "description": "Reason for current status"
          },
          "completed": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Completion timestamp"
          },
          "orders": {
            "type": "object",
            "description": "Orders associated with this payment link"
          },
          "customer": {
            "$ref": "#/components/schemas/Customer"
          }
        }
      },
      "OrderStatusChangedEvent": {
        "type": "object",
        "description": "Webhook event for order status changes",
        "properties": {
          "event": {
            "type": "string",
            "const": "status_changed"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project identifier"
          },
          "order_id": {
            "type": "string",
            "format": "uuid",
            "description": "Order identifier"
          }
        }
      },
      "TransactionStatusChangedEvent": {
        "type": "object",
        "description": "Webhook event for transaction status changes",
        "properties": {
          "event": {
            "type": "string",
            "const": "transaction_status_changed"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid",
            "description": "Merchant identifier"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project identifier"
          },
          "order_id": {
            "type": "string",
            "format": "uuid",
            "description": "Order identifier"
          },
          "transaction_id": {
            "type": "string",
            "format": "uuid",
            "description": "Transaction identifier"
          },
          "transaction_status": {
            "type": "string",
            "enum": [
              "new",
              "pending",
              "processing",
              "accepted",
              "captured",
              "completed",
              "cancelled",
              "error",
              "expired"
            ]
          }
        }
      },
      "SearchOrder": {
        "type": "object",
        "description": "Simplified order object returned by search",
        "properties": {
          "amount": {
            "type": "integer",
            "readOnly": true,
            "description": "Order amount"
          },
          "description": {
            "type": "string",
            "readOnly": true,
            "description": "Order description"
          },
          "currency": {
            "type": "string",
            "readOnly": true,
            "description": "Currency code"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "status",
              "type",
              "value"
            ],
            "properties": {
              "status": {
                "type": "integer",
                "minimum": 400,
                "maximum": 599,
                "description": "HTTP status code"
              },
              "type": {
                "type": "string",
                "description": "Error type identifier"
              },
              "value": {
                "type": "string",
                "description": "Human-readable error description"
              },
              "property_path": {
                "type": "string",
                "readOnly": true,
                "description": "Path to the property that failed validation"
              },
              "property_description": {
                "type": "string",
                "description": "Description of the failing property"
              }
            }
          }
        }
      }
    }
  }
}