{
  "openapi": "3.1.0",
  "info": {
    "title": "TagihanAI API",
    "version": "v1",
    "description": "Dokumentasi API TagihanAI untuk integrasi invoice, billing, payment, webhook, autentikasi API key, rate limit, dan approval aplikasi developer."
  },
  "servers": [
    {
      "url": "https://www.tagihanai.com"
    }
  ],
  "externalDocs": {
    "description": "TagihanAI API Documentation",
    "url": "https://www.tagihanai.com/api-documentation"
  },
  "tags": [
    {
      "name": "Transactions",
      "description": "Unified document model supporting Invoice, Bill, Credit Note, and Debit Note types. External invoice apps can use external_source + external_invoice_id for idempotent invoice sync."
    },
    {
      "name": "Parties",
      "description": "Unified API for customers and vendors. Use the role parameter to filter."
    },
    {
      "name": "Payments",
      "description": "Payment transactions linked to invoices and bills."
    },
    {
      "name": "Subscriptions",
      "description": "Recurring billing subscriptions with state management."
    },
    {
      "name": "Webhooks",
      "description": "Manage outbound webhook subscriptions to receive real-time event notifications."
    },
    {
      "name": "Settings",
      "description": "Workspace document, email template, invoice delivery, and invoice style settings for external invoice apps. Document number formats are intentionally excluded."
    },
    {
      "name": "Public",
      "description": "Public endpoints that do not require authentication. Includes free invoice creation and developer app registration for administrator review."
    }
  ],
  "paths": {
    "/api/v1/transactions": {
      "get": {
        "tags": [
          "Transactions"
        ],
        "summary": "List transactions",
        "description": "Retrieve a paginated list of transactions with optional filters.",
        "operationId": "getapiV1Transactions",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Filter by type: INVOICE, BILL, CREDIT_NOTE, DEBIT_NOTE",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by transaction status",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "payment_status",
            "in": "query",
            "required": false,
            "description": "Filter: UNPAID, PARTIAL, PAID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "description": "Filter by document_date >= (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "description": "Filter by document_date <= (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_before",
            "in": "query",
            "required": false,
            "description": "Filter by due_date <= (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Search document_number and receiver_name",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number (default: 1)",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Items per page (default: 20, max: 100)",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort field:direction, e.g. created_at:desc",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "party_id",
            "in": "query",
            "required": false,
            "description": "Filter by counterparty UUID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "550e8400-e29b-41d4-a716-446655440000",
                      "type": "INVOICE",
                      "document_number": "INV-2026-0042",
                      "document_date": "2026-02-10",
                      "due_date": "2026-03-10",
                      "status": "SENT",
                      "payment_status": "UNPAID",
                      "total": 1500000,
                      "paid_amount": 0,
                      "receiver_name": "PT Maju Jaya",
                      "description": "Web development services",
                      "created_at": "2026-02-10T08:30:00Z"
                    }
                  ],
                  "pagination": {
                    "total": 142,
                    "page": 1,
                    "per_page": 20,
                    "has_more": true
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "transactions:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Transactions"
        ],
        "summary": "Create transaction",
        "description": "Create or idempotently upsert a transaction. External invoice apps should send external_source and external_invoice_id to avoid duplicates.",
        "operationId": "postapiV1Transactions",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "550e8400-e29b-41d4-a716-446655440000",
                    "type": "INVOICE",
                    "status": "DRAFT",
                    "payment_status": "UNPAID",
                    "total": 1500000,
                    "living_invoice_url": "https://tagihanai.com/invoice/public/abc123...",
                    "created_at": "2026-02-10T08:30:00Z"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "transactions:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "INVOICE",
                      "BILL",
                      "CREDIT_NOTE",
                      "DEBIT_NOTE"
                    ],
                    "description": "Transaction type"
                  },
                  "amount": {
                    "type": "number",
                    "description": "Total amount. Use total for new integrations; amount is accepted for compatibility."
                  },
                  "total": {
                    "type": "number",
                    "description": "Total amount"
                  },
                  "document_number": {
                    "type": "string",
                    "description": "Document number (auto-generated if omitted)"
                  },
                  "document_date": {
                    "type": "string",
                    "description": "Document date (YYYY-MM-DD)"
                  },
                  "due_date": {
                    "type": "string",
                    "description": "Due date (YYYY-MM-DD)"
                  },
                  "counterparty_name": {
                    "type": "string",
                    "description": "Customer or vendor name"
                  },
                  "counterparty_email": {
                    "type": "string",
                    "description": "Customer or vendor email"
                  },
                  "counterparty_phone": {
                    "type": "string",
                    "description": "Customer or vendor phone/WhatsApp"
                  },
                  "counterparty_id": {
                    "type": "string",
                    "description": "Counterparty UUID (alternative to counterparty_name)"
                  },
                  "external_source": {
                    "type": "string",
                    "description": "Workspace integration source slug, e.g. custom_app"
                  },
                  "external_invoice_id": {
                    "type": "string",
                    "description": "Stable invoice ID from the source app"
                  },
                  "pdf_url": {
                    "type": "string",
                    "description": "Optional official PDF snapshot URL from the source app"
                  },
                  "line_items": {
                    "type": "array",
                    "items": {},
                    "description": "Optional line items with product_name/name, quantity, unit_price/price, description"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description or notes"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Custom metadata (key-value pairs)"
                  }
                },
                "required": [
                  "type",
                  "total"
                ]
              },
              "example": {
                "type": "INVOICE",
                "external_source": "custom_app",
                "external_invoice_id": "INV-EXT-1001",
                "total": 1500000,
                "document_date": "2026-02-10",
                "due_date": "2026-03-10",
                "counterparty_name": "PT Maju Jaya",
                "counterparty_email": "finance@majujaya.example",
                "description": "Web development services"
              }
            }
          }
        }
      }
    },
    "/api/v1/transactions/{id}": {
      "get": {
        "tags": [
          "Transactions"
        ],
        "summary": "Get transaction",
        "description": "Retrieve a single transaction by ID.",
        "operationId": "getapiV1TransactionsId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "550e8400-e29b-41d4-a716-446655440000",
                    "type": "INVOICE",
                    "document_number": "INV-2026-0042",
                    "status": "SENT",
                    "payment_status": "UNPAID",
                    "total": 1500000,
                    "paid_amount": 0,
                    "receiver_name": "PT Maju Jaya",
                    "metadata": {}
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "transactions:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Transactions"
        ],
        "summary": "Update transaction",
        "description": "Update a transaction. Draft transactions update in place; sent unpaid transactions are treated as revisions. Financial fields are locked after partial or full payment.",
        "operationId": "patchapiV1TransactionsId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "550e8400-e29b-41d4-a716-446655440000",
                    "due_date": "2026-04-10"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "transactions:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "document_number": {
                    "type": "string",
                    "description": "Document number"
                  },
                  "document_date": {
                    "type": "string",
                    "description": "Document date (YYYY-MM-DD)"
                  },
                  "due_date": {
                    "type": "string",
                    "description": "Due date (YYYY-MM-DD)"
                  },
                  "counterparty_name": {
                    "type": "string",
                    "description": "Customer or vendor name"
                  },
                  "total": {
                    "type": "number",
                    "description": "Total amount"
                  },
                  "amount": {
                    "type": "number",
                    "description": "Total amount alias for compatibility"
                  },
                  "line_items": {
                    "type": "array",
                    "items": {},
                    "description": "Optional replacement line items"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Custom metadata (key-value pairs)"
                  }
                },
                "required": []
              },
              "example": {
                "due_date": "2026-04-10",
                "description": "Updated description"
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Transactions"
        ],
        "summary": "Cancel transaction",
        "description": "Cancel a transaction. Paid and partially paid transactions cannot be deleted; use a reversal, credit note, or refund flow instead.",
        "operationId": "deleteapiV1TransactionsId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content"
          }
        },
        "x-required-scope": "transactions:write",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/api/v1/transactions/{id}/actions/{action}": {
      "post": {
        "tags": [
          "Transactions"
        ],
        "summary": "Transition transaction state",
        "description": "Execute a state transition on a transaction. Available actions for external invoice apps: send, cancel, mark_paid.",
        "operationId": "postapiV1TransactionsIdActionsAction",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "550e8400-e29b-41d4-a716-446655440000",
                    "status": "SENT",
                    "payment_status": "UNPAID",
                    "living_invoice_url": "https://tagihanai.com/invoice/public/abc123..."
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "transactions:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expected_version": {
                    "type": "integer",
                    "description": "Optimistic locking version (from metadata.version)"
                  },
                  "payload": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Additional data for the transition"
                  }
                },
                "required": []
              },
              "example": {
                "expected_version": 3,
                "payload": {
                  "notes": "Approved by finance team"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/transactions/{id}/payments": {
      "get": {
        "tags": [
          "Transactions"
        ],
        "summary": "List transaction payments",
        "description": "Retrieve a paginated list of payments linked to a specific transaction.",
        "operationId": "getapiV1TransactionsIdPayments",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Items per page",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "uuid",
                      "transaction_id": "550e8400-e29b-41d4-a716-446655440000",
                      "status": "PAID",
                      "amount": 500000,
                      "payment_method": "bank_transfer",
                      "paid_at": "2026-02-10T10:00:00Z"
                    }
                  ],
                  "pagination": {
                    "total": 2,
                    "page": 1,
                    "per_page": 20,
                    "has_more": false
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "transactions:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Transactions"
        ],
        "summary": "Record manual payment",
        "description": "Record an idempotent manual payment from the source app. Use external_source and external_payment_id when the payment was created outside TagihanAi.",
        "operationId": "postapiV1TransactionsIdPayments",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "payment": {
                      "id": "pay_123",
                      "status": "PAID",
                      "amount": 1500000
                    },
                    "transaction": {
                      "id": "550e8400-e29b-41d4-a716-446655440000",
                      "payment_status": "PAID"
                    },
                    "paid_amount": 1500000,
                    "outstanding_amount": 0,
                    "payment_status": "PAID"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "payments:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "external_source": {
                    "type": "string",
                    "description": "Workspace integration source slug"
                  },
                  "external_payment_id": {
                    "type": "string",
                    "description": "Stable payment ID from the source app"
                  },
                  "amount": {
                    "type": "number",
                    "description": "Payment amount"
                  },
                  "payment_date": {
                    "type": "string",
                    "description": "Payment date (YYYY-MM-DD or ISO 8601)"
                  },
                  "payment_method": {
                    "type": "string",
                    "description": "Payment method label, e.g. bank_transfer"
                  },
                  "notes": {
                    "type": "string",
                    "description": "Optional payment notes"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Custom metadata"
                  }
                },
                "required": [
                  "amount"
                ]
              },
              "example": {
                "external_source": "custom_app",
                "external_payment_id": "PAY-EXT-7788",
                "amount": 1500000,
                "payment_date": "2026-06-30",
                "payment_method": "bank_transfer",
                "notes": "Recorded manually in source app"
              }
            }
          }
        }
      }
    },
    "/api/v1/parties": {
      "get": {
        "tags": [
          "Parties"
        ],
        "summary": "List parties",
        "description": "List customers and/or vendors.",
        "operationId": "getapiV1Parties",
        "parameters": [
          {
            "name": "role",
            "in": "query",
            "required": false,
            "description": "Filter: customer, vendor (omit for both)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Search name, email, phone",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Items per page",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "uuid",
                      "role": "customer",
                      "name": "PT Maju Jaya",
                      "email": "billing@majujaya.com"
                    }
                  ],
                  "pagination": {
                    "total": 50,
                    "page": 1,
                    "per_page": 20,
                    "has_more": true
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "parties:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Parties"
        ],
        "summary": "Create party",
        "description": "Create a new customer or vendor.",
        "operationId": "postapiV1Parties",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "role": "customer",
                    "name": "PT Maju Jaya",
                    "email": "billing@majujaya.com"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "parties:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "customer",
                      "vendor"
                    ],
                    "description": "Role: customer or vendor"
                  },
                  "email": {
                    "type": "string",
                    "description": "Email address"
                  },
                  "phone": {
                    "type": "string",
                    "description": "Phone number"
                  },
                  "address": {
                    "type": "string",
                    "description": "Address"
                  }
                },
                "required": [
                  "name",
                  "role"
                ]
              },
              "example": {
                "name": "PT Maju Jaya",
                "role": "customer",
                "email": "billing@majujaya.com"
              }
            }
          }
        }
      }
    },
    "/api/v1/parties/{id}": {
      "get": {
        "tags": [
          "Parties"
        ],
        "summary": "Get party",
        "description": "Retrieve a single customer or vendor by ID.",
        "operationId": "getapiV1PartiesId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "role": "vendor",
                    "name": "Vendor Corp",
                    "email": "vendor@corp.com"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "parties:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Parties"
        ],
        "summary": "Update party",
        "description": "Update a customer or vendor.",
        "operationId": "patchapiV1PartiesId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "name": "PT Maju Jaya",
                    "email": "new@email.com"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "parties:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name"
                  },
                  "email": {
                    "type": "string",
                    "description": "Email"
                  },
                  "phone": {
                    "type": "string",
                    "description": "Phone"
                  },
                  "address": {
                    "type": "string",
                    "description": "Address"
                  }
                },
                "required": []
              },
              "example": {
                "email": "new@email.com"
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Parties"
        ],
        "summary": "Delete party",
        "description": "Remove a customer or vendor.",
        "operationId": "deleteapiV1PartiesId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content"
          }
        },
        "x-required-scope": "parties:write",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/api/v1/payments": {
      "get": {
        "tags": [
          "Payments"
        ],
        "summary": "List payments",
        "description": "List payment transactions.",
        "operationId": "getapiV1Payments",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter: PENDING, PROCESSING, PAID, FAILED, EXPIRED, CANCELLED",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "transaction_id",
            "in": "query",
            "required": false,
            "description": "Filter by parent transaction UUID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "description": "Filter by created_at >= (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "description": "Filter by created_at <= (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Items per page",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "uuid",
                      "transaction_id": "uuid",
                      "status": "PAID",
                      "amount": 500000,
                      "payment_method": "bank_transfer",
                      "paid_at": "2026-02-10T10:00:00Z"
                    }
                  ],
                  "pagination": {
                    "has_more": false
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "payments:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/api/v1/payments/{id}": {
      "get": {
        "tags": [
          "Payments"
        ],
        "summary": "Get payment",
        "description": "Retrieve a single payment transaction.",
        "operationId": "getapiV1PaymentsId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "transaction_id": "uuid",
                    "status": "PAID",
                    "amount": 500000,
                    "gateway_provider": "xendit",
                    "payment_method": "bank_transfer"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "payments:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/api/v1/subscriptions": {
      "get": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "List subscriptions",
        "description": "List subscriptions with optional filters.",
        "operationId": "getapiV1Subscriptions",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter: active, paused, cancelled, expired",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Items per page",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "uuid",
                      "service_name": "Cloud Hosting",
                      "status": "active",
                      "amount": 500000,
                      "billing_period": "monthly",
                      "next_billing_date": "2026-03-01"
                    }
                  ],
                  "pagination": {
                    "has_more": false
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "subscriptions:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Create subscription",
        "description": "Create a new subscription.",
        "operationId": "postapiV1Subscriptions",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "service_name": "Cloud Hosting",
                    "status": "active"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "subscriptions:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "service_name": {
                    "type": "string",
                    "description": "Service name"
                  },
                  "amount": {
                    "type": "number",
                    "description": "Billing amount"
                  },
                  "billing_period": {
                    "type": "string",
                    "enum": [
                      "monthly",
                      "quarterly",
                      "yearly"
                    ],
                    "description": "Billing cycle"
                  },
                  "start_date": {
                    "type": "string",
                    "description": "Start date (YYYY-MM-DD)"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description or notes"
                  }
                },
                "required": [
                  "service_name",
                  "amount",
                  "billing_period"
                ]
              },
              "example": {
                "service_name": "Cloud Hosting",
                "amount": 500000,
                "billing_period": "monthly"
              }
            }
          }
        }
      }
    },
    "/api/v1/subscriptions/{id}": {
      "get": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Get subscription",
        "description": "Retrieve a single subscription.",
        "operationId": "getapiV1SubscriptionsId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "service_name": "Cloud Hosting",
                    "status": "active",
                    "amount": 500000
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "subscriptions:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Update subscription",
        "description": "Update subscription details.",
        "operationId": "patchapiV1SubscriptionsId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "amount": 600000
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "subscriptions:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "service_name": {
                    "type": "string",
                    "description": "Service name"
                  },
                  "amount": {
                    "type": "number",
                    "description": "Amount"
                  },
                  "billing_period": {
                    "type": "string",
                    "enum": [
                      "monthly",
                      "quarterly",
                      "yearly"
                    ],
                    "description": "Billing cycle"
                  },
                  "start_date": {
                    "type": "string",
                    "description": "Start date (YYYY-MM-DD)"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description or notes"
                  }
                },
                "required": []
              },
              "example": {
                "amount": 600000
              }
            }
          }
        }
      }
    },
    "/api/v1/subscriptions/{id}/actions/{action}": {
      "post": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Transition subscription state",
        "description": "Execute a state transition. Actions: activate, pause, resume, cancel.",
        "operationId": "postapiV1SubscriptionsIdActionsAction",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "success": true,
                    "subscription_id": "uuid",
                    "status": "paused"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "subscriptions:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expected_version": {
                    "type": "integer",
                    "description": "Optimistic locking version"
                  }
                },
                "required": []
              },
              "example": {
                "expected_version": 1
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook subscriptions",
        "description": "List all webhook subscriptions for your workspace.",
        "operationId": "getapiV1Webhooks",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "uuid",
                      "url": "https://example.com/webhook",
                      "event_types": [
                        "transaction.paid"
                      ],
                      "is_active": true,
                      "consecutive_failures": 0,
                      "last_delivery_at": "2026-02-10T10:00:00Z"
                    }
                  ]
                }
              }
            }
          }
        },
        "x-required-scope": "webhooks:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Create webhook subscription",
        "description": "Create a new webhook subscription. A signing secret will be auto-generated.",
        "operationId": "postapiV1Webhooks",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "url": "https://example.com/webhook",
                    "signing_secret": "whsec_abc123...",
                    "event_types": [
                      "transaction.created",
                      "transaction.paid"
                    ]
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "webhooks:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "HTTPS webhook endpoint URL"
                  },
                  "event_types": {
                    "type": "array",
                    "items": {},
                    "description": "Event types to subscribe to (use [\"*\"] for all)"
                  },
                  "description": {
                    "type": "string",
                    "description": "Human-readable description"
                  }
                },
                "required": [
                  "url",
                  "event_types"
                ]
              },
              "example": {
                "url": "https://example.com/webhook",
                "event_types": [
                  "transaction.created",
                  "transaction.paid"
                ],
                "description": "ERP Integration"
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Get webhook subscription",
        "description": "Retrieve a single webhook subscription.",
        "operationId": "getapiV1WebhooksId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "url": "https://example.com/webhook",
                    "is_active": true
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "webhooks:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Update webhook subscription",
        "description": "Update webhook URL, event types, or status.",
        "operationId": "patchapiV1WebhooksId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "uuid",
                    "event_types": [
                      "*"
                    ],
                    "is_active": true
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "webhooks:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "Webhook URL"
                  },
                  "event_types": {
                    "type": "array",
                    "items": {},
                    "description": "Event types"
                  },
                  "is_active": {
                    "type": "boolean",
                    "description": "Active status"
                  }
                },
                "required": []
              },
              "example": {
                "event_types": [
                  "*"
                ],
                "is_active": true
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete webhook subscription",
        "description": "Permanently delete a webhook subscription.",
        "operationId": "deleteapiV1WebhooksId",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content"
          }
        },
        "x-required-scope": "webhooks:write",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/api/v1/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List delivery logs",
        "description": "View delivery attempts and their results for a webhook subscription.",
        "operationId": "getapiV1WebhooksIdDeliveries",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter: success, failed, dead_letter",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Items per page",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "uuid",
                      "event_type": "transaction.paid",
                      "status": "success",
                      "response_status": 200,
                      "response_time_ms": 245,
                      "attempt_number": 1,
                      "created_at": "2026-02-10T10:00:00Z"
                    }
                  ]
                }
              }
            }
          }
        },
        "x-required-scope": "webhooks:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/api/v1/webhooks/{id}/test": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Send test event",
        "description": "Send a synthetic test event to verify your webhook endpoint.",
        "operationId": "postapiV1WebhooksIdTest",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "success": true,
                    "status_code": 200,
                    "response_time_ms": 150
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "webhooks:write",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      }
    },
    "/api/v1/settings/document-email": {
      "get": {
        "tags": [
          "Settings"
        ],
        "summary": "Get document email settings",
        "description": "Read the workspace settings used by Settings > Dokumen & Email, including invoice delivery defaults, email templates, invoice style, and company display data.",
        "operationId": "getapiV1SettingsDocumentEmail",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "workspace_id": "uuid",
                    "invoice_send_settings": {
                      "default_delivery_channels": [
                        "email",
                        "whatsapp",
                        "link"
                      ],
                      "default_include_payment_link": true,
                      "default_link_visibility": "public",
                      "default_link_expiry": "30d"
                    },
                    "email_templates": [
                      {
                        "template_type": "invoice_generated",
                        "subject_template": "Invoice {{invoice_number}} dari {{company_name}}",
                        "is_active": true,
                        "version": 2
                      }
                    ],
                    "invoice_style": {
                      "template_id": "zahir-modern",
                      "invoice_label": "INVOICE",
                      "invoice_text_color": "#111827"
                    },
                    "company": {
                      "company_name": "PT Contoh Jaya",
                      "company_logo": "https://cdn.example.com/logo.png"
                    },
                    "blocked_fields": [
                      "document_number_formats"
                    ]
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "settings:read",
        "security": [
          {
            "bearerAuth": []
          }
        ]
      },
      "put": {
        "tags": [
          "Settings"
        ],
        "summary": "Sync document email settings",
        "description": "Update invoice delivery defaults, email templates, company display data, promo banner settings, and invoice style. Format Nomor Dokumen is ignored and must remain managed by TagihanAI.",
        "operationId": "putapiV1SettingsDocumentEmail",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "workspace_id": "uuid",
                    "updated": {
                      "invoice_settings": true,
                      "email_templates": 1,
                      "invoice_style": true,
                      "company": true
                    },
                    "blocked_fields": [
                      "document_number_formats"
                    ],
                    "updated_at": "2026-06-30T05:30:00.000Z"
                  }
                }
              }
            }
          }
        },
        "x-required-scope": "settings:write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "invoice_send_settings": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Default delivery channel, payment link, logo visibility, tax, and notes settings"
                  },
                  "email_templates": {
                    "type": "array",
                    "items": {},
                    "description": "Email templates keyed by template_type with subject_template, body_template, variables, configuration, and is_active"
                  },
                  "invoice_style": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Invoice label, colors, fonts, display toggles, and footer text"
                  },
                  "company": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Company logo, email, website, address, and optional company_name"
                  },
                  "promo_banner": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Optional Living Invoice promo banner settings"
                  }
                },
                "required": []
              },
              "example": {
                "invoice_send_settings": {
                  "default_delivery_channels": [
                    "email",
                    "whatsapp",
                    "link"
                  ],
                  "default_include_payment_link": true,
                  "default_link_visibility": "public",
                  "default_link_expiry": "30d",
                  "default_show_company_logo_on_living": true,
                  "default_show_company_logo_on_email": true
                },
                "email_templates": [
                  {
                    "template_type": "invoice_generated",
                    "template_name": "Invoice dari Zahir",
                    "subject_template": "Invoice {{invoice_number}} dari {{company_name}}",
                    "body_template": "Halo {{customer_name}}, silakan buka {{invoice_link}}.",
                    "is_active": true,
                    "configuration": {
                      "channels": [
                        "email"
                      ],
                      "include_payment_link": true,
                      "link_expiry": "30d"
                    }
                  }
                ],
                "invoice_style": {
                  "template_id": "zahir-modern",
                  "invoice_label": "INVOICE",
                  "invoice_text_color": "#111827",
                  "table_header_background_color": "#0F766E",
                  "table_background_color": "#F8FAFC",
                  "total_background_color": "#0F766E",
                  "invoice_title_font": "Inter",
                  "header_font": "Inter",
                  "body_font": "Inter",
                  "show_company_logo": true,
                  "show_company_address": true,
                  "show_customer_address": true,
                  "show_footer": true,
                  "footer_text": "Terima kasih atas kepercayaan Anda."
                },
                "company": {
                  "company_logo": "https://zahir-assets.example.com/company-logo.png",
                  "company_email": "billing@company.co.id",
                  "company_website": "https://company.co.id",
                  "company_address": "Jl. Contoh No. 10, Jakarta"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/create-invoice": {
      "post": {
        "tags": [
          "Public"
        ],
        "summary": "Create invoice (public)",
        "description": "Create an invoice without authentication. Automatically creates a user account and workspace for the given email. If the email already exists, returns a login redirect instead.",
        "operationId": "postapiV1PublicCreateInvoice",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "invoice_id": "uuid",
                  "document_number": "INV-0001",
                  "public_url": "/invoice/public/abc123...",
                  "workspace_id": "uuid",
                  "total": 8000000
                }
              }
            }
          }
        },
        "x-required-scope": "public",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "Email address for account creation"
                  },
                  "company_name": {
                    "type": "string",
                    "description": "Sender company name (optional)"
                  },
                  "customer_name": {
                    "type": "string",
                    "description": "Customer/recipient name"
                  },
                  "items": {
                    "type": "array",
                    "items": {},
                    "description": "Line items with description, quantity, unit_price"
                  },
                  "due_date": {
                    "type": "string",
                    "description": "Due date in YYYY-MM-DD format (optional)"
                  },
                  "notes": {
                    "type": "string",
                    "description": "Additional notes (optional)"
                  },
                  "description": {
                    "type": "string",
                    "description": "Invoice description (optional)"
                  }
                },
                "required": [
                  "email",
                  "customer_name",
                  "items"
                ]
              },
              "example": {
                "email": "user@example.com",
                "company_name": "PT Contoh Jaya",
                "customer_name": "PT Pelanggan Utama",
                "items": [
                  {
                    "description": "Jasa Konsultasi IT",
                    "quantity": 1,
                    "unit_price": 5000000
                  },
                  {
                    "description": "Setup Server",
                    "quantity": 2,
                    "unit_price": 1500000
                  }
                ],
                "due_date": "2026-04-01",
                "notes": "Pembayaran via transfer bank"
              }
            }
          }
        }
      }
    },
    "/api/developer/app-requests": {
      "post": {
        "tags": [
          "Public"
        ],
        "summary": "Register developer app",
        "description": "Submit a third-party application for TagihanAI administrator review. Humans should use /developer#register for the guided signup form; this endpoint is available for automated partner workflows. Approved apps can receive sandbox and live partner credentials.",
        "operationId": "postapiDeveloperAppRequests",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "request": {
                      "id": "uuid",
                      "app_name": "Zahir Smart Invoice",
                      "source_slug": "zahir",
                      "status": "submitted",
                      "submitted_at": "2026-06-30T10:00:00Z"
                    }
                  },
                  "message": "Registrasi aplikasi diterima untuk review administrator."
                }
              }
            }
          }
        },
        "x-required-scope": "public",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "app_name": {
                    "type": "string",
                    "description": "Application display name"
                  },
                  "source_slug": {
                    "type": "string",
                    "description": "Unique source slug, lowercase letters/numbers/dash/underscore"
                  },
                  "company_name": {
                    "type": "string",
                    "description": "Legal or public company name"
                  },
                  "company_website": {
                    "type": "string",
                    "description": "Company website URL"
                  },
                  "contact_name": {
                    "type": "string",
                    "description": "Technical or business contact name"
                  },
                  "contact_email": {
                    "type": "string",
                    "description": "Business email for review follow-up"
                  },
                  "technical_contact_email": {
                    "type": "string",
                    "description": "Alias accepted for contact_email"
                  },
                  "business_contact_email": {
                    "type": "string",
                    "description": "Alias accepted for contact_email"
                  },
                  "app_category": {
                    "type": "string",
                    "description": "Application category"
                  },
                  "callback_domains": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ],
                    "description": "HTTPS callback or webhook domain(s), comma-separated or array"
                  },
                  "integration_use_case": {
                    "type": "string",
                    "description": "Integration use case and expected data flow"
                  },
                  "requested_scopes": {
                    "type": "array",
                    "items": {},
                    "description": "Optional requested scopes. Defaults include transaction, payment, webhook, and document-email settings scopes."
                  },
                  "requested_webhook_events": {
                    "type": "array",
                    "items": {},
                    "description": "Optional webhook events requested for approval."
                  }
                },
                "required": [
                  "app_name",
                  "source_slug",
                  "company_name",
                  "contact_email",
                  "app_category",
                  "callback_domains",
                  "integration_use_case"
                ]
              },
              "example": {
                "app_name": "Zahir Smart Invoice",
                "source_slug": "zahir",
                "company_name": "PT Zahir Internasional",
                "company_website": "https://zahironline.com",
                "contact_name": "Zahir Technical Team",
                "technical_contact_email": "developer@zahironline.com",
                "business_contact_email": "partnerships@zahironline.com",
                "app_category": "ERP or accounting",
                "callback_domains": "https://app.zahironline.com",
                "integration_use_case": "Push sales invoices to TagihanAI, generate Living Invoice URLs, sync manual payments, and receive payment webhooks."
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key"
      }
    }
  }
}
