{
  "openapi": "3.0.1",
  "info": {
    "title": "PatientPayments API",
    "description": "Create bill pay payment links for patient balances and receive signed webhooks as they are paid, refunded, or disputed.\n\n**Authentication** — send your key as `Authorization: Bearer pp_live_…` (or `pp_test_…`). Test keys only ever see test resources and never move money.\n\n**Errors** — every non-2xx response is `{ \"error\": { \"code\", \"message\", \"param\", \"requestId\" } }`. Match on `code`.\n\n**Rate limits** — 120 requests per minute per key by default (`Retry-After` is set on 429), 600 per minute per IP, and 5,000 payment links per key per day.\n\n**Webhooks** — see the `x-webhook-events` and `x-webhook-signature` extensions in this document, and the integration guide at https://patientpayments.com/developers/docs.",
    "termsOfService": "https://patientpayments.com/terms",
    "contact": {
      "name": "PatientPayments Developer Support",
      "url": "https://patientpayments.com/contact"
    },
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://api.patientpayments.com",
      "description": "Production (live and test keys)"
    }
  ],
  "paths": {
    "/api/v1/locations": {
      "get": {
        "tags": [
          "Locations"
        ],
        "summary": "List locations",
        "description": "Returns every active location this API key can act on, ordered by name.",
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResourcePagedList"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/locations/{id}": {
      "get": {
        "tags": [
          "Locations"
        ],
        "summary": "Retrieve a location",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Location id (`loc_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/payment-links": {
      "post": {
        "tags": [
          "Payment Links"
        ],
        "summary": "Create a payment link",
        "description": "Requires an `Idempotency-Key` header. Repeating a request with the same key and body\r\nreturns the original response with `Idempotency-Replayed: true`.\r\n            \r\nThe patient is matched to an existing record in your practice by `patient.externalId`\r\nfirst, then by phone number. If nothing matches, the link stores the contact details and a\r\npatient record is created when they pay. Test keys never link to existing patients.\r\n            \r\nLinks created with a test key (`pp_test_`) are marked `test: true`, never charge\r\nanyone, and are driven through their lifecycle with `POST /v1/payment-links/{id}/simulate`.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Any unique string (a UUID is ideal) up to 200 characters. Repeating a request with the same key and body returns the original response instead of creating a second resource. Keys are remembered for 24 hours.",
            "required": true,
            "schema": {
              "maxLength": 200,
              "type": "string",
              "example": "c5c8f6a2-5f3e-4a9d-9b3e-2f6b1c0a7d10"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/CreatePaymentLinkRequest"
                  }
                ],
                "description": "Request body for creating a payment link."
              }
            },
            "text/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/CreatePaymentLinkRequest"
                  }
                ],
                "description": "Request body for creating a payment link."
              }
            },
            "application/*+json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/CreatePaymentLinkRequest"
                  }
                ],
                "description": "Request body for creating a payment link."
              }
            }
          }
        },
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "headers": {
              "Idempotency-Replayed": {
                "description": "Present and `true` when this response was replayed from an earlier request with the same Idempotency-Key.",
                "schema": {
                  "type": "boolean"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResource"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Content",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Payment Links"
        ],
        "summary": "List payment links",
        "description": "Newest first. Test keys see only test links; live keys see only live links.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Filter by status: `active`, `paid`, `expired`, `cancelled`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "externalReference",
            "in": "query",
            "description": "Exact match on your reference.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "locationId",
            "in": "query",
            "description": "Only links at this location (`loc_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "createdAfter",
            "in": "query",
            "description": "Only links created at or after this time (UTC).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "description": "Only links created before this time (UTC).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "paidAfter",
            "in": "query",
            "description": "Only links paid at or after this time (UTC). Use with `status=paid` for reconciliation.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number.",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Items per page, 1–100 (default 50).",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResourcePagedList"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/payment-links/{id}": {
      "get": {
        "tags": [
          "Payment Links"
        ],
        "summary": "Retrieve a payment link",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Payment link id (`plink_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Payment Links"
        ],
        "summary": "Update a payment link",
        "description": "Only `active` links can be updated, and only the fields in the request schema. To\r\nclear `externalReference` or `metadata`, send them as `null`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Payment link id (`plink_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Fields to change. Omitted fields are left as they are.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/UpdatePaymentLinkRequest"
                  }
                ],
                "description": "Request body for updating an active payment link. Only the listed fields can change.\r\nOmitted fields are left as they are; send `null` for `externalReference` or\r\n`metadata` to clear them."
              }
            },
            "text/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/UpdatePaymentLinkRequest"
                  }
                ],
                "description": "Request body for updating an active payment link. Only the listed fields can change.\r\nOmitted fields are left as they are; send `null` for `externalReference` or\r\n`metadata` to clear them."
              }
            },
            "application/*+json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/UpdatePaymentLinkRequest"
                  }
                ],
                "description": "Request body for updating an active payment link. Only the listed fields can change.\r\nOmitted fields are left as they are; send `null` for `externalReference` or\r\n`metadata` to clear them."
              }
            }
          }
        },
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResource"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/payment-links/{id}/cancel": {
      "post": {
        "tags": [
          "Payment Links"
        ],
        "summary": "Cancel a payment link",
        "description": "The hosted page stops accepting payment and `payment_link.cancelled` is sent. Only `active` links can be cancelled.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Payment link id (`plink_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/payment-links/{id}/simulate": {
      "post": {
        "tags": [
          "Payment Links"
        ],
        "summary": "Simulate a payment outcome (test mode)",
        "description": "Test keys only. Moves a test link through the same state changes a real payment would and\r\nsends the matching webhooks, so you can exercise your integration end to end without money\r\nmoving. Outcomes:\r\n            \r\n- `paid` — card payment succeeds: `payment_link.paid`\r\n- `processing` — bank debit submitted: `payment_link.processing`\r\n- `processing_then_paid` — bank debit submitted and settles: `payment_link.processing` then `payment_link.paid`\r\n- `failed` — bank debit returned: `payment_link.failed`\r\n- `expired` — link passes its expiry: `payment_link.expired`\r\n            \r\nTest links never carry a transaction record; the simulated payment appears only in the webhook payload.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Payment link id (`plink_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "The outcome to simulate.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/SimulatePaymentLinkRequest"
                  }
                ],
                "description": "Request body for simulating a payment outcome on a test-mode link."
              }
            },
            "text/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/SimulatePaymentLinkRequest"
                  }
                ],
                "description": "Request body for simulating a payment outcome on a test-mode link."
              }
            },
            "application/*+json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/SimulatePaymentLinkRequest"
                  }
                ],
                "description": "Request body for simulating a payment outcome on a test-mode link."
              }
            }
          }
        },
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLinkResource"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhook-deliveries": {
      "get": {
        "tags": [
          "Webhook Deliveries"
        ],
        "summary": "List deliveries",
        "description": "Newest first. Payloads are omitted from the list; retrieve a single delivery to see its body.",
        "parameters": [
          {
            "name": "endpointId",
            "in": "query",
            "description": "Only deliveries to this endpoint (`we_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "paymentLinkId",
            "in": "query",
            "description": "Only deliveries about this payment link (`plink_…`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "One of `pending`, `retrying`, `delivered`, `exhausted`, `skipped`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "Event type, for example `payment_link.paid`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "description": "Only deliveries created at or after this time (UTC).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number.",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Items per page, 1–100 (default 50).",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResourcePagedList"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhook-deliveries/{id}": {
      "get": {
        "tags": [
          "Webhook Deliveries"
        ],
        "summary": "Retrieve a delivery",
        "description": "Includes the exact JSON body that was (or will be) POSTed to your endpoint.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Event id (`evt_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhook-deliveries/{id}/redeliver": {
      "post": {
        "tags": [
          "Webhook Deliveries"
        ],
        "summary": "Redeliver an event",
        "description": "Queues the delivery again with the same event id and a fresh retry ladder. Deliveries that are already pending or retrying are left alone.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Event id (`evt_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhook-endpoints": {
      "get": {
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "List webhook endpoints",
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResourcePagedList"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Create a webhook endpoint",
        "description": "The response includes `secret` exactly once. Store it; it is used to verify the\r\n`PatientPayments-Signature` header on every delivery. The URL must be public HTTPS.\r\nA practice may have at most 10 live and 10 test endpoints.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/CreateWebhookEndpointRequest"
                  }
                ],
                "description": "Request body for registering a webhook endpoint."
              }
            },
            "text/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/CreateWebhookEndpointRequest"
                  }
                ],
                "description": "Request body for registering a webhook endpoint."
              }
            },
            "application/*+json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/CreateWebhookEndpointRequest"
                  }
                ],
                "description": "Request body for registering a webhook endpoint."
              }
            }
          }
        },
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResource"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhook-endpoints/{id}": {
      "get": {
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Retrieve a webhook endpoint",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Endpoint id (`we_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Update a webhook endpoint",
        "description": "Change the URL, event list, or description, or enable / disable delivery. A disabled endpoint keeps its secret and can be replayed after re-enabling.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Endpoint id (`we_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Fields to change. Omitted fields are left as they are.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/UpdateWebhookEndpointRequest"
                  }
                ],
                "description": "Request body for updating a webhook endpoint. Omitted fields are unchanged."
              }
            },
            "text/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/UpdateWebhookEndpointRequest"
                  }
                ],
                "description": "Request body for updating a webhook endpoint. Omitted fields are unchanged."
              }
            },
            "application/*+json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/UpdateWebhookEndpointRequest"
                  }
                ],
                "description": "Request body for updating a webhook endpoint. Omitted fields are unchanged."
              }
            }
          }
        },
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResource"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Delete a webhook endpoint",
        "description": "Deletes the endpoint and its delivery history. This cannot be undone.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Endpoint id (`we_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhook-endpoints/{id}/replay": {
      "post": {
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Replay events",
        "description": "Re-sends events for payment links that changed state since `since` (at most 30 days\r\nago): deliveries that never succeeded are re-queued with their original event ids, and\r\nstate changes that happened while the endpoint was disabled are queued fresh. Limited to\r\none replay per endpoint every 10 minutes.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Endpoint id (`we_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "The replay window; `since` is required.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/ReplayWebhookEventsRequest"
                  }
                ],
                "description": "Request body for replaying events to an endpoint."
              }
            },
            "text/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/ReplayWebhookEventsRequest"
                  }
                ],
                "description": "Request body for replaying events to an endpoint."
              }
            },
            "application/*+json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/ReplayWebhookEventsRequest"
                  }
                ],
                "description": "Request body for replaying events to an endpoint."
              }
            }
          }
        },
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReplayWebhookEventsResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhook-endpoints/{id}/rotate-secret": {
      "post": {
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Rotate the signing secret",
        "description": "Returns a new `secret`. For the next 24 hours deliveries are signed with both the new\r\nand the previous secret (two `v1=` values in the header), so you can switch without\r\ndropping events.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Endpoint id (`we_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhook-endpoints/{id}/test": {
      "post": {
        "tags": [
          "Webhook Endpoints"
        ],
        "summary": "Send a test event",
        "description": "Queues a signed `ping` event through the normal delivery pipeline. Poll `GET /api/v1/webhook-deliveries/{id}` with the returned id to see the result.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Endpoint id (`we_…`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ApiError": {
        "type": "object",
        "properties": {
          "error": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ApiErrorDetail"
              }
            ],
            "description": "Error details."
          }
        },
        "additionalProperties": false,
        "description": "Error envelope returned by every non-2xx Developer API response."
      },
      "ApiErrorDetail": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable machine-readable code. Match on this, not on `message`.",
            "example": "validation_error"
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation. Wording may change between releases.",
            "example": "amount must be between 0.01 and 999999.99"
          },
          "param": {
            "type": "string",
            "description": "The request field the error refers to, when applicable.",
            "nullable": true,
            "example": "amount"
          },
          "requestId": {
            "type": "string",
            "description": "Correlation id for this request. Quote it when contacting support.",
            "nullable": true,
            "example": "0HN7G3K2Q9V1A:00000003"
          }
        },
        "additionalProperties": false,
        "description": "Error details."
      },
      "CreatePaymentLinkRequest": {
        "required": [
          "amount",
          "description",
          "patient"
        ],
        "type": "object",
        "properties": {
          "amount": {
            "maximum": 999999.99,
            "minimum": 0.01,
            "type": "number",
            "description": "Amount to collect, in dollars. Between 0.01 and 999999.99.",
            "format": "double",
            "example": 185
          },
          "currency": {
            "maxLength": 3,
            "minLength": 0,
            "type": "string",
            "description": "ISO currency code. Only `usd` is supported; defaults to `usd`.",
            "nullable": true,
            "example": "usd"
          },
          "description": {
            "maxLength": 500,
            "minLength": 1,
            "type": "string",
            "description": "What the patient is paying for. Shown on the payment page and the receipt.",
            "example": "Crown - tooth #14"
          },
          "patient": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PaymentLinkPatientInput"
              }
            ],
            "description": "The patient who owes the balance."
          },
          "externalReference": {
            "maxLength": 100,
            "minLength": 0,
            "type": "string",
            "description": "Your own reference for this balance (invoice, ledger, or claim id). Searchable.",
            "nullable": true,
            "example": "INV-2026-00123"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Up to 20 string key/value pairs (2 KB total) echoed back on the resource and in every webhook.",
            "nullable": true,
            "example": {
              "ledgerAccount": "4410",
              "provider": "Dr. Ellis"
            }
          },
          "expiresAt": {
            "type": "string",
            "description": "When the link stops accepting payment (UTC). Defaults to 30 days from creation; max 365 days.",
            "format": "date-time",
            "nullable": true,
            "example": "2026-11-30T23:59:59Z"
          },
          "locationId": {
            "maxLength": 40,
            "minLength": 0,
            "type": "string",
            "description": "Location the balance belongs to. Required when the key has access to more than one active\r\nlocation. Optional for keys pinned to a single location, but if supplied it must match that location.",
            "nullable": true,
            "example": "loc_7b1e2c7a4a0b4f6a8d9c5e3f2a1b0c9d"
          }
        },
        "additionalProperties": false,
        "description": "Request body for creating a payment link."
      },
      "CreateWebhookEndpointRequest": {
        "required": [
          "url"
        ],
        "type": "object",
        "properties": {
          "url": {
            "maxLength": 2048,
            "minLength": 0,
            "type": "string",
            "description": "Public HTTPS URL that receives events. Private, loopback, and link-local addresses are rejected.",
            "example": "https://api.example.com/patientpayments/webhook"
          },
          "enabledEvents": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Event types to deliver. Omit or send an empty list to receive every event type.",
            "nullable": true,
            "example": [
              "payment_link.paid",
              "payment_link.failed"
            ]
          },
          "description": {
            "maxLength": 200,
            "minLength": 0,
            "type": "string",
            "description": "Optional label shown in the PatientPayments app.",
            "nullable": true,
            "example": "Production ledger sync"
          },
          "locationId": {
            "maxLength": 40,
            "minLength": 0,
            "type": "string",
            "description": "Restrict this endpoint to one location. Omit to receive events for every location the key can see.\r\nA key pinned to a location may only create endpoints for that location.",
            "nullable": true,
            "example": "loc_7b1e2c7a4a0b4f6a8d9c5e3f2a1b0c9d"
          }
        },
        "additionalProperties": false,
        "description": "Request body for registering a webhook endpoint."
      },
      "DisputeResource": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "description": "Processor dispute status, for example `needs_response`, `under_review`, `won`, `lost`.",
            "example": "needs_response"
          },
          "openedAt": {
            "type": "string",
            "description": "When the dispute was opened (UTC).",
            "format": "date-time",
            "nullable": true,
            "example": "2026-10-22T09:15:00Z"
          }
        },
        "additionalProperties": false,
        "description": "Dispute (chargeback or inquiry) details on a payment."
      },
      "LocationRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque id. Always starts with `loc_`.",
            "example": "loc_7b1e2c7a4a0b4f6a8d9c5e3f2a1b0c9d"
          },
          "name": {
            "type": "string",
            "description": "Location name.",
            "example": "Downtown Dental"
          }
        },
        "additionalProperties": false,
        "description": "Minimal location reference embedded in other resources."
      },
      "LocationResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque id. Always starts with `loc_`.",
            "example": "loc_7b1e2c7a4a0b4f6a8d9c5e3f2a1b0c9d"
          },
          "object": {
            "type": "string",
            "description": "Always `location`.",
            "example": "location"
          },
          "name": {
            "type": "string",
            "description": "Location name.",
            "example": "Downtown Dental"
          },
          "city": {
            "type": "string",
            "description": "City.",
            "nullable": true,
            "example": "Sandpoint"
          },
          "state": {
            "type": "string",
            "description": "Two-letter state code.",
            "nullable": true,
            "example": "ID"
          },
          "timeZone": {
            "type": "string",
            "description": "IANA time zone of the office.",
            "nullable": true,
            "example": "America/Los_Angeles"
          }
        },
        "additionalProperties": false,
        "description": "A location (office) within the practice."
      },
      "LocationResourcePagedList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "description": "Always `list`.",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LocationResource"
            },
            "description": "Items on this page."
          },
          "page": {
            "type": "integer",
            "description": "1-based page number.",
            "format": "int32",
            "example": 1
          },
          "pageSize": {
            "type": "integer",
            "description": "Items per page (max 100).",
            "format": "int32",
            "example": 50
          },
          "totalCount": {
            "type": "integer",
            "description": "Total matching items across all pages.",
            "format": "int32",
            "example": 312
          },
          "hasMore": {
            "type": "boolean",
            "description": "True when more pages follow.",
            "example": true
          }
        },
        "additionalProperties": false,
        "description": "A page of results."
      },
      "PaymentLinkPatientInput": {
        "required": [
          "firstName",
          "lastName",
          "phone"
        ],
        "type": "object",
        "properties": {
          "firstName": {
            "maxLength": 100,
            "minLength": 1,
            "type": "string",
            "description": "Patient first name.",
            "example": "Jordan"
          },
          "lastName": {
            "maxLength": 100,
            "minLength": 1,
            "type": "string",
            "description": "Patient last name.",
            "example": "Rivera"
          },
          "phone": {
            "maxLength": 20,
            "minLength": 10,
            "type": "string",
            "description": "Mobile number in any common US format; stored as E.164.",
            "example": "+12085551234"
          },
          "email": {
            "maxLength": 255,
            "minLength": 0,
            "type": "string",
            "description": "Email address for the receipt. Optional.",
            "format": "email",
            "nullable": true,
            "example": "jordan.rivera@example.com"
          },
          "externalId": {
            "maxLength": 100,
            "minLength": 0,
            "type": "string",
            "description": "Your system's patient id (for example the PMS chart number).",
            "nullable": true,
            "example": "PMS-48213"
          }
        },
        "additionalProperties": false,
        "description": "Patient details supplied when creating a link. No PatientPayments identifiers are accepted;\r\nthe link is matched to an existing patient by `externalId` or phone within your practice."
      },
      "PaymentLinkPatientResource": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "string",
            "description": "First name.",
            "nullable": true,
            "example": "Jordan"
          },
          "lastName": {
            "type": "string",
            "description": "Last name.",
            "nullable": true,
            "example": "Rivera"
          },
          "phone": {
            "type": "string",
            "description": "E.164 mobile number.",
            "nullable": true,
            "example": "+12085551234"
          },
          "email": {
            "type": "string",
            "description": "Email address.",
            "nullable": true,
            "example": "jordan.rivera@example.com"
          },
          "externalId": {
            "type": "string",
            "description": "Your system's patient id, if supplied.",
            "nullable": true,
            "example": "PMS-48213"
          }
        },
        "additionalProperties": false,
        "description": "Patient details on a payment link."
      },
      "PaymentLinkPatientUpdate": {
        "type": "object",
        "properties": {
          "email": {
            "maxLength": 255,
            "minLength": 0,
            "type": "string",
            "description": "Corrected email address.",
            "format": "email",
            "nullable": true,
            "example": "jordan.rivera@example.com"
          },
          "phone": {
            "maxLength": 20,
            "minLength": 10,
            "type": "string",
            "description": "Corrected mobile number.",
            "nullable": true,
            "example": "+12085551234"
          }
        },
        "additionalProperties": false,
        "description": "Patient contact fields that may be corrected on an active link."
      },
      "PaymentLinkResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque id. Always starts with `plink_`.",
            "example": "plink_3f2a9c1d4e5b4f6a8d9c5e3f2a1b0c9d"
          },
          "object": {
            "type": "string",
            "description": "Always `payment_link`.",
            "example": "payment_link"
          },
          "url": {
            "type": "string",
            "description": "Public URL the patient opens to pay.",
            "example": "https://secure.patientpayments.com/pay/K7M2P9QX"
          },
          "status": {
            "type": "string",
            "description": "One of `active`, `paid`, `expired`, `cancelled`.",
            "example": "active"
          },
          "test": {
            "type": "boolean",
            "description": "True for links created with a test key. Test links never move money.",
            "example": false
          },
          "amount": {
            "type": "number",
            "description": "Amount in dollars.",
            "format": "double",
            "example": 185
          },
          "currency": {
            "type": "string",
            "description": "ISO currency code.",
            "example": "usd"
          },
          "description": {
            "type": "string",
            "description": "Description shown to the patient.",
            "example": "Crown - tooth #14"
          },
          "externalReference": {
            "type": "string",
            "description": "Your reference, if supplied.",
            "nullable": true,
            "example": "INV-2026-00123"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Your metadata, if supplied.",
            "nullable": true
          },
          "patient": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PaymentLinkPatientResource"
              }
            ],
            "description": "Patient details as stored on the link."
          },
          "location": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LocationRef"
              }
            ],
            "description": "Location the balance belongs to."
          },
          "source": {
            "type": "string",
            "description": "How the link was created: `api`, `staff`, or `website`.",
            "example": "api"
          },
          "expiresAt": {
            "type": "string",
            "description": "When the link stops accepting payment (UTC).",
            "format": "date-time",
            "example": "2026-11-30T23:59:59Z"
          },
          "paidAt": {
            "type": "string",
            "description": "When the payment succeeded (UTC). Null until paid.",
            "format": "date-time",
            "nullable": true,
            "example": "2026-10-15T17:42:10Z"
          },
          "createdAt": {
            "type": "string",
            "description": "When the link was created (UTC).",
            "format": "date-time",
            "example": "2026-10-14T18:03:55Z"
          },
          "transaction": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TransactionResource"
              }
            ],
            "description": "The payment, once one exists (including a pending ACH debit). Null while unpaid.",
            "nullable": true
          },
          "refunds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RefundResource"
            },
            "description": "Refunds issued against the payment, newest first. Empty when none."
          }
        },
        "additionalProperties": false,
        "description": "A payment link."
      },
      "PaymentLinkResourcePagedList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "description": "Always `list`.",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentLinkResource"
            },
            "description": "Items on this page."
          },
          "page": {
            "type": "integer",
            "description": "1-based page number.",
            "format": "int32",
            "example": 1
          },
          "pageSize": {
            "type": "integer",
            "description": "Items per page (max 100).",
            "format": "int32",
            "example": 50
          },
          "totalCount": {
            "type": "integer",
            "description": "Total matching items across all pages.",
            "format": "int32",
            "example": 312
          },
          "hasMore": {
            "type": "boolean",
            "description": "True when more pages follow.",
            "example": true
          }
        },
        "additionalProperties": false,
        "description": "A page of results."
      },
      "RefundResource": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "description": "Refunded amount in dollars (positive).",
            "format": "double",
            "example": 50
          },
          "currency": {
            "type": "string",
            "description": "ISO currency code.",
            "example": "usd"
          },
          "reason": {
            "type": "string",
            "description": "Reason entered by the office, if any.",
            "nullable": true,
            "example": "Insurance paid remainder"
          },
          "createdAt": {
            "type": "string",
            "description": "When the refund was issued (UTC).",
            "format": "date-time",
            "example": "2026-10-20T15:02:44Z"
          }
        },
        "additionalProperties": false,
        "description": "A refund issued against a payment."
      },
      "ReplayWebhookEventsRequest": {
        "required": [
          "since"
        ],
        "type": "object",
        "properties": {
          "since": {
            "type": "string",
            "description": "Re-send events for links that changed state at or after this time (UTC). At most 30 days ago.",
            "format": "date-time",
            "example": "2026-10-10T00:00:00Z"
          }
        },
        "additionalProperties": false,
        "description": "Request body for replaying events to an endpoint."
      },
      "ReplayWebhookEventsResult": {
        "type": "object",
        "properties": {
          "queued": {
            "type": "integer",
            "description": "Number of events queued for delivery.",
            "format": "int32",
            "example": 42
          }
        },
        "additionalProperties": false,
        "description": "Result of a replay request."
      },
      "SimulatePaymentLinkRequest": {
        "required": [
          "outcome"
        ],
        "type": "object",
        "properties": {
          "outcome": {
            "maxLength": 40,
            "minLength": 0,
            "type": "string",
            "description": "One of `paid`, `processing`, `processing_then_paid`, `failed`, `expired`.",
            "example": "paid"
          }
        },
        "additionalProperties": false,
        "description": "Request body for simulating a payment outcome on a test-mode link."
      },
      "TransactionResource": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "description": "One of `pending`, `succeeded`, `failed`, `refunded`.",
            "example": "succeeded"
          },
          "amount": {
            "type": "number",
            "description": "Gross amount charged, in dollars.",
            "format": "double",
            "example": 185
          },
          "currency": {
            "type": "string",
            "description": "ISO currency code.",
            "example": "usd"
          },
          "fee": {
            "type": "number",
            "description": "Card-processing fee, in dollars.",
            "format": "double",
            "example": 5.67
          },
          "net": {
            "type": "number",
            "description": "Amount after fees, in dollars.",
            "format": "double",
            "example": 179.33
          },
          "paymentMethodType": {
            "type": "string",
            "description": "`card` or `us_bank_account`.",
            "nullable": true,
            "example": "card"
          },
          "paymentMethodBrand": {
            "type": "string",
            "description": "Card brand or bank name.",
            "nullable": true,
            "example": "visa"
          },
          "paymentMethodLast4": {
            "type": "string",
            "description": "Last four digits of the card or account.",
            "nullable": true,
            "example": "4242"
          },
          "receiptUrl": {
            "type": "string",
            "description": "Hosted receipt URL, when available.",
            "nullable": true,
            "example": "https://pay.stripe.com/receipts/..."
          },
          "failureReason": {
            "type": "string",
            "description": "Why the payment failed, when it did.",
            "nullable": true,
            "example": "Your card was declined."
          },
          "processedAt": {
            "type": "string",
            "description": "When the processor finalized the payment (UTC).",
            "format": "date-time",
            "nullable": true,
            "example": "2026-10-15T17:42:10Z"
          },
          "dispute": {
            "allOf": [
              {
                "$ref": "#/components/schemas/DisputeResource"
              }
            ],
            "description": "Dispute details when the charge has been disputed. Null otherwise.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "A payment against a link. Has no id of its own in v1; it is always read through the link."
      },
      "UpdatePaymentLinkRequest": {
        "type": "object",
        "properties": {
          "amount": {
            "maximum": 999999.99,
            "minimum": 0.01,
            "type": "number",
            "description": "New amount in dollars.",
            "format": "double",
            "nullable": true,
            "example": 160
          },
          "description": {
            "maxLength": 500,
            "minLength": 1,
            "type": "string",
            "description": "New description.",
            "nullable": true,
            "example": "Crown - tooth #14 (adjusted)"
          },
          "patient": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PaymentLinkPatientUpdate"
              }
            ],
            "description": "Patient contact fields that may be corrected.",
            "nullable": true
          },
          "externalReference": {
            "maxLength": 100,
            "minLength": 0,
            "type": "string",
            "description": "New external reference.",
            "nullable": true,
            "example": "INV-2026-00123-R1"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Replacement metadata object. Replaces the whole object; it is not merged.",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "description": "New expiry (UTC). Must be in the future and within 365 days.",
            "format": "date-time",
            "nullable": true,
            "example": "2026-12-15T23:59:59Z"
          }
        },
        "additionalProperties": false,
        "description": "Request body for updating an active payment link. Only the listed fields can change.\r\nOmitted fields are left as they are; send `null` for `externalReference` or\r\n`metadata` to clear them."
      },
      "UpdateWebhookEndpointRequest": {
        "type": "object",
        "properties": {
          "url": {
            "maxLength": 2048,
            "minLength": 0,
            "type": "string",
            "description": "New URL. Re-validated like a new endpoint.",
            "nullable": true,
            "example": "https://api.example.com/patientpayments/webhook-v2"
          },
          "enabledEvents": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Replacement event list. An empty list means every event type.",
            "nullable": true,
            "example": [
              "payment_link.paid"
            ]
          },
          "description": {
            "maxLength": 200,
            "minLength": 0,
            "type": "string",
            "description": "New label.",
            "nullable": true,
            "example": "Production ledger sync (v2)"
          },
          "enabled": {
            "type": "boolean",
            "description": "Set `true` to re-enable an endpoint that was disabled (by you or automatically after\r\nrepeated failures). Set `false` to pause delivery; events are still recorded and can be replayed.",
            "nullable": true,
            "example": true
          }
        },
        "additionalProperties": false,
        "description": "Request body for updating a webhook endpoint. Omitted fields are unchanged."
      },
      "WebhookDeliveryResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Event id. Always starts with `evt_`. Identical across retries and redelivery; use it to ignore duplicates.",
            "example": "evt_1a2b3c4d5e6f47a8b9c0d1e2f3a4b5c6"
          },
          "object": {
            "type": "string",
            "description": "Always `webhook_delivery`.",
            "example": "webhook_delivery"
          },
          "type": {
            "type": "string",
            "description": "Event type.",
            "example": "payment_link.paid"
          },
          "endpointId": {
            "type": "string",
            "description": "Endpoint this delivery targets.",
            "example": "we_9d8c7b6a5f4e4d3c2b1a0f9e8d7c6b5a"
          },
          "paymentLinkId": {
            "type": "string",
            "description": "Payment link the event is about, when applicable.",
            "nullable": true,
            "example": "plink_3f2a9c1d4e5b4f6a8d9c5e3f2a1b0c9d"
          },
          "status": {
            "type": "string",
            "description": "One of `pending`, `retrying`, `delivered`, `exhausted`, `skipped`.",
            "example": "delivered"
          },
          "attempts": {
            "type": "integer",
            "description": "Attempts made so far.",
            "format": "int32",
            "example": 1
          },
          "nextAttemptAt": {
            "type": "string",
            "description": "Next scheduled attempt (UTC), while pending or retrying.",
            "format": "date-time",
            "nullable": true,
            "example": "2026-10-15T17:45:10Z"
          },
          "lastResponseCode": {
            "type": "integer",
            "description": "HTTP status returned by your endpoint on the last attempt.",
            "format": "int32",
            "nullable": true,
            "example": 200
          },
          "lastError": {
            "type": "string",
            "description": "Short reason for the last failure, when any.",
            "nullable": true,
            "example": "Timed out after 10s"
          },
          "createdAt": {
            "type": "string",
            "description": "When the event was created (UTC).",
            "format": "date-time",
            "example": "2026-10-15T17:42:11Z"
          },
          "deliveredAt": {
            "type": "string",
            "description": "When your endpoint acknowledged the event (UTC).",
            "format": "date-time",
            "nullable": true,
            "example": "2026-10-15T17:42:12Z"
          },
          "payload": {
            "allOf": [
              {
                "$ref": "#/components/schemas/WebhookEventPayload"
              }
            ],
            "description": "The exact JSON body that was (or will be) POSTed.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "A delivery attempt record for one event to one endpoint."
      },
      "WebhookDeliveryResourcePagedList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "description": "Always `list`.",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDeliveryResource"
            },
            "description": "Items on this page."
          },
          "page": {
            "type": "integer",
            "description": "1-based page number.",
            "format": "int32",
            "example": 1
          },
          "pageSize": {
            "type": "integer",
            "description": "Items per page (max 100).",
            "format": "int32",
            "example": 50
          },
          "totalCount": {
            "type": "integer",
            "description": "Total matching items across all pages.",
            "format": "int32",
            "example": 312
          },
          "hasMore": {
            "type": "boolean",
            "description": "True when more pages follow.",
            "example": true
          }
        },
        "additionalProperties": false,
        "description": "A page of results."
      },
      "WebhookEndpointResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque id. Always starts with `we_`.",
            "example": "we_9d8c7b6a5f4e4d3c2b1a0f9e8d7c6b5a"
          },
          "object": {
            "type": "string",
            "description": "Always `webhook_endpoint`.",
            "example": "webhook_endpoint"
          },
          "url": {
            "type": "string",
            "description": "Destination URL.",
            "example": "https://api.example.com/patientpayments/webhook"
          },
          "enabledEvents": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Event types delivered. Empty means every event type.",
            "example": [
              "payment_link.paid",
              "payment_link.failed"
            ]
          },
          "description": {
            "type": "string",
            "description": "Label.",
            "nullable": true,
            "example": "Production ledger sync"
          },
          "test": {
            "type": "boolean",
            "description": "True for endpoints registered with a test key.",
            "example": false
          },
          "status": {
            "type": "string",
            "description": "`enabled` or `disabled`.",
            "example": "enabled"
          },
          "disabledReason": {
            "type": "string",
            "description": "Why the endpoint is disabled, when it is.",
            "nullable": true,
            "example": "Disabled automatically after 20 consecutive failed deliveries"
          },
          "location": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LocationRef"
              }
            ],
            "description": "Location filter, or null for every location.",
            "nullable": true
          },
          "secret": {
            "type": "string",
            "description": "Signing secret. Present only in the response to create and rotate-secret; never returned again.",
            "nullable": true,
            "example": "whsec_Yk3c9w2M..."
          },
          "createdAt": {
            "type": "string",
            "description": "When the link was created (UTC).",
            "format": "date-time",
            "example": "2026-10-14T18:03:55Z"
          }
        },
        "additionalProperties": false,
        "description": "A registered webhook endpoint."
      },
      "WebhookEndpointResourcePagedList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "description": "Always `list`.",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpointResource"
            },
            "description": "Items on this page."
          },
          "page": {
            "type": "integer",
            "description": "1-based page number.",
            "format": "int32",
            "example": 1
          },
          "pageSize": {
            "type": "integer",
            "description": "Items per page (max 100).",
            "format": "int32",
            "example": 50
          },
          "totalCount": {
            "type": "integer",
            "description": "Total matching items across all pages.",
            "format": "int32",
            "example": 312
          },
          "hasMore": {
            "type": "boolean",
            "description": "True when more pages follow.",
            "example": true
          }
        },
        "additionalProperties": false,
        "description": "A page of results."
      },
      "WebhookEventContext": {
        "type": "object",
        "properties": {
          "failureReason": {
            "type": "string",
            "description": "Failure reason for `payment_link.failed`.",
            "nullable": true,
            "example": "Your card was declined."
          },
          "refundAmount": {
            "type": "number",
            "description": "Amount refunded, in dollars, for `payment_link.refunded`.",
            "format": "double",
            "nullable": true,
            "example": 50
          },
          "disputeReason": {
            "type": "string",
            "description": "Dispute reason for `payment_link.disputed`.",
            "nullable": true,
            "example": "fraudulent"
          },
          "disputeAmount": {
            "type": "number",
            "description": "Dispute amount, in dollars, for `payment_link.disputed`.",
            "format": "double",
            "nullable": true,
            "example": 185
          },
          "evidenceDueBy": {
            "type": "string",
            "description": "Evidence due date (UTC) for `payment_link.disputed`.",
            "format": "date-time",
            "nullable": true,
            "example": "2026-11-01T23:59:59Z"
          },
          "disputeOutcome": {
            "type": "string",
            "description": "`won` or `lost` for `payment_link.dispute_closed`.",
            "nullable": true,
            "example": "won"
          },
          "triggeredBy": {
            "type": "string",
            "description": "`api`, `staff`, or `system` for `payment_link.cancelled`; `simulated` for test-mode outcomes.",
            "nullable": true,
            "example": "staff"
          }
        },
        "additionalProperties": false,
        "description": "Event-specific context."
      },
      "WebhookEventData": {
        "type": "object",
        "properties": {
          "paymentLink": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PaymentLinkResource"
              }
            ],
            "description": "The payment link in its state at the time of the event.",
            "nullable": true
          },
          "context": {
            "allOf": [
              {
                "$ref": "#/components/schemas/WebhookEventContext"
              }
            ],
            "description": "Extra context for some event types (dispute reason, refund amount, failure reason).",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Event data."
      },
      "WebhookEventPayload": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Event id. Always starts with `evt_`. Identical across retries; store it to ignore duplicates.",
            "example": "evt_1a2b3c4d5e6f47a8b9c0d1e2f3a4b5c6"
          },
          "object": {
            "type": "string",
            "description": "Always `event`.",
            "example": "event"
          },
          "type": {
            "type": "string",
            "description": "Event type, for example `payment_link.paid`.",
            "example": "payment_link.paid"
          },
          "test": {
            "type": "boolean",
            "description": "True when the event concerns a test-mode link.",
            "example": false
          },
          "createdAt": {
            "type": "string",
            "description": "When the event was created (UTC).",
            "format": "date-time",
            "example": "2026-10-15T17:42:11Z"
          },
          "data": {
            "allOf": [
              {
                "$ref": "#/components/schemas/WebhookEventData"
              }
            ],
            "description": "Event data."
          }
        },
        "additionalProperties": false,
        "description": "The body POSTed to your endpoint for every event."
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "description": "Tenant API key issued under API & Webhooks in the PatientPayments app.",
        "scheme": "bearer",
        "bearerFormat": "pp_live_… or pp_test_…"
      }
    }
  },
  "security": [
    {
      "ApiKey": [ ]
    }
  ],
  "tags": [
    {
      "name": "Payment Links",
      "description": "Create hosted payment pages for patient balances and track them to completion."
    },
    {
      "name": "Locations",
      "description": "Offices within the practice. Needed when a key can see more than one location."
    },
    {
      "name": "Webhook Endpoints",
      "description": "Register HTTPS URLs that receive signed events."
    },
    {
      "name": "Webhook Deliveries",
      "description": "Inspect, redeliver, and replay webhook events."
    },
    {
      "name": "Locations",
      "description": "Locations (offices) within your practice. Use these ids when creating payment links and\r\nwebhook endpoints. Keys pinned to one location see only that location."
    },
    {
      "name": "Payment Links",
      "description": "Bill pay payment links. A link is a hosted page where a patient pays a balance by card or\r\nbank account; you receive webhooks as it moves through `processing`, `paid`,\r\n`failed`, `refunded`, `disputed`, `expired`, and `cancelled`."
    },
    {
      "name": "Webhook Deliveries",
      "description": "Delivery history for your webhook endpoints: what was sent, when, and how your server\r\nresponded. Deliveries are kept for 30 days once delivered and 90 days otherwise."
    },
    {
      "name": "Webhook Endpoints",
      "description": "Webhook endpoints receive signed `POST`s when payment links change state. Endpoints\r\nregistered with a test key receive only test events; live keys, only live events."
    }
  ],
  "x-webhook-events": [
    {
      "type": "payment_link.processing",
      "description": "A bank (ACH) payment was submitted and is awaiting settlement (3–5 business days). The link's status becomes `paid`; `data.paymentLink.transaction.status` is `pending`.",
      "payloadSchema": "#/components/schemas/WebhookEventPayload"
    },
    {
      "type": "payment_link.paid",
      "description": "The payment succeeded. For cards this is immediate; for bank payments it follows `payment_link.processing` once the debit settles.",
      "payloadSchema": "#/components/schemas/WebhookEventPayload"
    },
    {
      "type": "payment_link.failed",
      "description": "A bank payment was returned after submission. `data.context.failureReason` explains why. The link's status remains `paid` with `transaction.status` = `failed`; the balance is still owed.",
      "payloadSchema": "#/components/schemas/WebhookEventPayload"
    },
    {
      "type": "payment_link.refunded",
      "description": "The office refunded some or all of the payment, or the bank reversed it. `data.context.refundAmount` is the amount returned; `data.paymentLink.refunds` lists every refund so far.",
      "payloadSchema": "#/components/schemas/WebhookEventPayload"
    },
    {
      "type": "payment_link.disputed",
      "description": "The patient's bank opened a dispute (chargeback). `data.context` carries `disputeReason`, `disputeAmount`, and `evidenceDueBy`.",
      "payloadSchema": "#/components/schemas/WebhookEventPayload"
    },
    {
      "type": "payment_link.dispute_closed",
      "description": "A dispute was resolved. `data.context.disputeOutcome` is `won` or `lost`.",
      "payloadSchema": "#/components/schemas/WebhookEventPayload"
    },
    {
      "type": "payment_link.expired",
      "description": "The link passed its `expiresAt` without being paid.",
      "payloadSchema": "#/components/schemas/WebhookEventPayload"
    },
    {
      "type": "payment_link.cancelled",
      "description": "The link was cancelled by your integration (`data.context.triggeredBy` = `api`) or by office staff (`staff`).",
      "payloadSchema": "#/components/schemas/WebhookEventPayload"
    },
    {
      "type": "ping",
      "description": "Sent only when you call `POST /v1/webhook-endpoints/{id}/test`. `data` is empty.",
      "payloadSchema": "#/components/schemas/WebhookEventPayload"
    }
  ],
  "x-webhook-signature": {
    "header": "PatientPayments-Signature",
    "format": "t=<unix seconds>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>",
    "tolerance": "300 seconds",
    "rotation": "For 24 hours after rotate-secret, two v1= values are present; accept the request if any matches.",
    "otherHeaders": [
      "PatientPayments-Event-Id",
      "PatientPayments-Event-Type"
    ]
  }
}