{
  "openapi": "3.1.0",
  "info": {
    "title": "Lago API Discovery Profile",
    "version": "1.0.0",
    "description": "A same-origin, machine-readable discovery profile for high-value Lago billing operations. Use https://swagger.getlago.com/openapi.yaml for the complete production contract.",
    "x-api-versioning-policy": "https://doc.getlago.com/api-reference/versioning",
    "contact": {
      "name": "Lago",
      "url": "https://doc.getlago.com/contact",
      "email": "hello@getlago.com"
    },
    "license": {
      "name": "AGPL-3.0",
      "identifier": "AGPL-3.0-only"
    },
    "x-official-sdks": [
      {
        "language": "JavaScript",
        "package": "lago-javascript-client",
        "registry": "https://registry.npmjs.org/lago-javascript-client/latest",
        "source": "https://github.com/getlago/lago-javascript-client"
      },
      {
        "language": "Python",
        "package": "lago-python-client",
        "registry": "https://pypi.org/project/lago-python-client/",
        "source": "https://github.com/getlago/lago-python-client"
      },
      {
        "language": "Ruby",
        "package": "lago-ruby-client",
        "registry": "https://rubygems.org/gems/lago-ruby-client",
        "source": "https://github.com/getlago/lago-ruby-client"
      },
      {
        "language": "Go",
        "package": "github.com/getlago/lago-go-client",
        "registry": "https://pkg.go.dev/github.com/getlago/lago-go-client",
        "source": "https://github.com/getlago/lago-go-client"
      }
    ]
  },
  "externalDocs": {
    "description": "Complete Lago API specification and developer documentation",
    "url": "https://swagger.getlago.com/openapi.yaml"
  },
  "servers": [
    {
      "url": "https://api.getlago.com",
      "description": "Lago Cloud US API"
    },
    {
      "url": "https://api.eu.getlago.com",
      "description": "Lago Cloud EU API"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Usage",
      "description": "Ingest metered product usage."
    },
    {
      "name": "Customers",
      "description": "Create and retrieve billable customers."
    },
    {
      "name": "Subscriptions",
      "description": "Subscribe customers to pricing plans."
    },
    {
      "name": "Plans",
      "description": "Discover configured pricing plans."
    },
    {
      "name": "Invoices",
      "description": "Retrieve generated invoices."
    }
  ],
  "paths": {
    "/api/v1/events": {
      "get": {
        "operationId": "listUsageEvents",
        "x-lago-required-api-key-permissions": ["event:read"],
        "summary": "List usage events",
        "description": "Returns a paginated list of usage events for the organization.",
        "tags": ["Usage"],
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of usage events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      },
      "post": {
        "operationId": "ingestUsageEvent",
        "x-lago-required-api-key-permissions": ["event:write"],
        "summary": "Ingest a usage event",
        "description": "Records an idempotent product-usage event for aggregation and billing. Supply a unique transaction_id for every event.",
        "tags": ["Usage"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The usage event was accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/api/v1/events/batch": {
      "post": {
        "operationId": "createBatchEvents",
        "x-lago-required-api-key-permissions": ["event:write"],
        "summary": "Batch multiple usage events",
        "description": "Sends up to 100 usage records in one request. Each event must carry its own unique transaction_id.",
        "tags": ["Usage"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventBatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The usage events were received for asynchronous processing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventBatchResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/api/v1/customers": {
      "post": {
        "operationId": "createCustomer",
        "x-lago-required-api-key-permissions": ["customer:write"],
        "summary": "Create a customer",
        "description": "Creates or updates the billing customer identified by external_id.",
        "tags": ["Customers"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The customer was created or updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/api/v1/customers/{external_id}": {
      "get": {
        "operationId": "getCustomer",
        "x-lago-required-api-key-permissions": ["customer:read"],
        "summary": "Retrieve a customer",
        "description": "Returns the customer whose external identifier matches the supplied value.",
        "tags": ["Customers"],
        "parameters": [
          {
            "$ref": "#/components/parameters/ExternalId"
          }
        ],
        "responses": {
          "200": {
            "description": "The requested customer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/api/v1/subscriptions": {
      "post": {
        "operationId": "createSubscription",
        "x-lago-required-api-key-permissions": ["subscription:write"],
        "summary": "Create a subscription",
        "description": "Subscribes a customer to a Lago plan using stable external identifiers.",
        "tags": ["Subscriptions"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The subscription was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/api/v1/plans": {
      "get": {
        "operationId": "listPlans",
        "x-lago-required-api-key-permissions": ["plan:read"],
        "summary": "List plans",
        "description": "Returns a paginated list of pricing plans available in the organization.",
        "tags": ["Plans"],
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of plans.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    },
    "/api/v1/invoices": {
      "get": {
        "operationId": "listInvoices",
        "x-lago-required-api-key-permissions": ["invoice:read"],
        "summary": "List invoices",
        "description": "Returns invoices for the organization, optionally filtered and paginated.",
        "tags": ["Invoices"],
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of invoices.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/UnexpectedError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Lago API key",
        "description": "Use Authorization: Bearer <api_key>. Lago Premium organizations with the enterprise API-permissions add-on can restrict keys by resource and read/write mode.",
        "x-lago-api-key-permission-model": {
          "format": "<resource>:<mode>",
          "modes": ["read", "write"],
          "availability": "Lago Premium enterprise add-on",
          "documentationUrl": "https://doc.getlago.com/guide/security/api-keys#set-api-key-permissions"
        }
      }
    },
    "parameters": {
      "ExternalId": {
        "name": "external_id",
        "in": "path",
        "required": true,
        "description": "Stable customer identifier from your application.",
        "schema": {
          "type": "string",
          "minLength": 1
        }
      },
      "Page": {
        "name": "page",
        "in": "query",
        "description": "One-based result page.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      },
      "PerPage": {
        "name": "per_page",
        "in": "query",
        "description": "Number of resources returned per page.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 100
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request is malformed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "The Lago API key is missing or invalid.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "status": 401,
              "error": "Unauthorized",
              "code": "unauthorized"
            }
          }
        }
      },
      "NotFound": {
        "description": "The requested resource does not exist.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "status": 404,
              "error": "Not Found",
              "code": "resource_not_found"
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "The request is valid JSON but fails semantic validation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "status": 422,
              "error": "Unprocessable Entity",
              "code": "validation_errors",
              "error_details": {
                "external_id": ["value_is_mandatory"]
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "The organization exceeded its REST API rate limit.",
        "headers": {
          "X-RateLimit-Limit": {
            "description": "Maximum requests permitted in the current window.",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          "X-RateLimit-Remaining": {
            "description": "Requests remaining in the current window.",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          "X-RateLimit-Reset": {
            "description": "Seconds until the current rate-limit window resets.",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Lago could not complete the request because of an internal server error.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "status": 500,
              "error": "Internal Server Error"
            }
          }
        }
      },
      "UnexpectedError": {
        "description": "Any other non-success response uses Lago's public REST error envelope.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      }
    },
    "schemas": {
      "ApiError": {
        "type": "object",
        "description": "Public Lago REST API error envelope. Unexpected production failures expose only status and error; validation failures can also include code and error_details.",
        "required": ["status", "error"],
        "properties": {
          "status": {
            "type": "integer",
            "description": "HTTP status code.",
            "minimum": 400,
            "maximum": 599
          },
          "error": {
            "type": "string",
            "description": "Human-readable error category."
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable error code."
          },
          "error_details": {
            "type": "object",
            "description": "Field-level validation details when available.",
            "additionalProperties": true
          }
        }
      },
      "EventInput": {
        "type": "object",
        "required": ["transaction_id", "external_customer_id", "code"],
        "properties": {
          "transaction_id": {
            "type": "string",
            "description": "Unique idempotency identifier for the event."
          },
          "external_customer_id": {
            "type": "string",
            "description": "Customer identifier from your application."
          },
          "code": {
            "type": "string",
            "description": "Billable metric code."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Time at which the usage occurred."
          },
          "properties": {
            "type": "object",
            "description": "Metric dimensions and numeric values used for aggregation.",
            "additionalProperties": true
          }
        }
      },
      "EventRequest": {
        "type": "object",
        "required": ["event"],
        "properties": {
          "event": {
            "$ref": "#/components/schemas/EventInput"
          }
        }
      },
      "EventResponse": {
        "type": "object",
        "required": ["event"],
        "properties": {
          "event": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "EventListResponse": {
        "type": "object",
        "required": ["events", "meta"],
        "properties": {
          "events": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "meta": {
            "$ref": "#/components/schemas/PaginationMeta"
          }
        }
      },
      "EventBatchRequest": {
        "type": "object",
        "required": ["events"],
        "properties": {
          "events": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/EventInput"
            }
          }
        }
      },
      "EventBatchResponse": {
        "type": "object",
        "required": ["events"],
        "properties": {
          "events": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "An accepted event. Processing continues asynchronously after receipt.",
              "additionalProperties": true
            }
          }
        }
      },
      "CustomerRequest": {
        "type": "object",
        "required": ["customer"],
        "properties": {
          "customer": {
            "type": "object",
            "required": ["external_id"],
            "properties": {
              "external_id": {
                "type": "string",
                "description": "Stable customer identifier from your application."
              },
              "name": {
                "type": "string",
                "description": "Display name used on billing documents."
              },
              "email": {
                "type": "string",
                "format": "email",
                "description": "Billing email address."
              },
              "currency": {
                "type": "string",
                "pattern": "^[A-Z]{3}$",
                "description": "Three-letter ISO 4217 currency code."
              }
            }
          }
        }
      },
      "CustomerResponse": {
        "type": "object",
        "required": ["customer"],
        "properties": {
          "customer": {
            "type": "object",
            "required": ["lago_id", "external_id"],
            "properties": {
              "lago_id": {
                "type": "string",
                "format": "uuid"
              },
              "external_id": {
                "type": "string"
              },
              "name": {
                "type": ["string", "null"]
              },
              "email": {
                "type": ["string", "null"],
                "format": "email"
              }
            }
          }
        }
      },
      "SubscriptionRequest": {
        "type": "object",
        "required": ["subscription"],
        "properties": {
          "subscription": {
            "type": "object",
            "required": ["external_customer_id", "plan_code", "external_id"],
            "properties": {
              "external_customer_id": {
                "type": "string"
              },
              "plan_code": {
                "type": "string"
              },
              "external_id": {
                "type": "string"
              },
              "billing_time": {
                "type": "string",
                "enum": ["calendar", "anniversary"],
                "default": "calendar"
              }
            }
          }
        }
      },
      "SubscriptionResponse": {
        "type": "object",
        "required": ["subscription"],
        "properties": {
          "subscription": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "PlanListResponse": {
        "type": "object",
        "required": ["plans", "meta"],
        "properties": {
          "plans": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["code", "name"],
              "properties": {
                "code": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "interval": {
                  "type": "string",
                  "enum": ["weekly", "monthly", "quarterly", "semiannual", "yearly"]
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/PaginationMeta"
          }
        }
      },
      "InvoiceListResponse": {
        "type": "object",
        "required": ["invoices", "meta"],
        "properties": {
          "invoices": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["lago_id", "status", "currency"],
              "properties": {
                "lago_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "status": {
                  "type": "string"
                },
                "currency": {
                  "type": "string",
                  "pattern": "^[A-Z]{3}$"
                },
                "total_amount_cents": {
                  "type": "integer"
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/PaginationMeta"
          }
        }
      },
      "PaginationMeta": {
        "type": "object",
        "required": ["current_page", "total_pages", "total_count"],
        "properties": {
          "current_page": {
            "type": "integer"
          },
          "next_page": {
            "type": ["integer", "null"]
          },
          "prev_page": {
            "type": ["integer", "null"]
          },
          "total_pages": {
            "type": "integer"
          },
          "total_count": {
            "type": "integer"
          }
        }
      }
    }
  }
}
