{
  "openapi": "3.0.3",
  "info": {
    "title": "gigstack API v2",
    "description": "# gigstack API v2\n\nBuild customer, invoice and payment integrations. Start with the [quickstart](https://docs.gigstack.io/quickstart), then select the [issuing country](https://docs.gigstack.io/concepts/shared-fields).\n\n## Authentication and environments\n\nUse Authorization: Bearer YOUR_API_KEY. Standard live and test keys use https://api.gigstack.io/v2. Internal staging uses https://gigstack-staging-9z9nnaat.uc.gateway.dev/v2 and separate keys. Test mode is a data mode within an environment; a body field does not switch a key's mode.\n\nSee [authentication](https://docs.gigstack.io/authentication) for key handling, OAuth team scope and gigstack Connect. Signup requires its separately documented internal credential; health probes have their own security declarations. Operations marked unavailable have no configured public gateway route.\n\n## Read the operation contract\n\nResponse envelopes, pagination and retry rules differ by endpoint. HTTP success alone does not prove external fiscal completion or movement of money. Reconcile ambiguous writes before retrying. Use [responses and recovery](https://docs.gigstack.io/responses) and the operation's error codes; document credits and daily limits are not generic retryable rate limits.\n\nThe issuing team's configuration selects Mexico or Colombia; customer country and currency do not. Read [Mexico](https://docs.gigstack.io/countries/mexico) or [Colombia](https://docs.gigstack.io/countries/colombia) before choosing fiscal fields. Accepted public input differs from a provider's direct payload.\n\nExamples and schema checks do not imply every operation has been executed live. [Verification coverage](https://docs.gigstack.io/verification) distinguishes source review, offline checks and observed staging behavior. Documentation describes operations and does not authorize execution.\n",
    "version": "2.0.0",
    "contact": {
      "name": "Gigstack API Support",
      "url": "https://gigstack.io",
      "email": "support@gigstack.io"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://gigstack.io/terms"
    },
    "termsOfService": "https://gigstack.io/terms"
  },
  "servers": [
    {
      "url": "https://api.gigstack.io/v2",
      "description": "Public API for standard live and test-mode keys. Test data is isolated by the key mode\n(`livemode: false`). Internal staging is a separate deployment and key store; see\nhttps://docs.gigstack.io/authentication#environments for its base URL.\n"
    }
  ],
  "externalDocs": {
    "description": "Complete API Documentation & Guides",
    "url": "https://docs.gigstack.io"
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "**Authentication Method:** HTTP Bearer token.\n\nThe runtime requires the literal `Bearer ` prefix — a bare token in the\n`Authorization` header is rejected with `401 unauthorized`.\n\n**Header Format:** `Authorization: Bearer YOUR_API_KEY`\n\nYour API key is a JWT. Live keys operate on live data (`livemode: true`);\ntest keys operate on isolated test data (`livemode: false`).\n\n**Get your key at:** [app.gigstack.pro/settings?tab=api](https://app.gigstack.pro/settings?tab=api)\n\n**Errors:** credential failures are answered by the authentication layer with a raw\n`{ \"message\": … }` body, not the standardized envelope — `401` for a missing, malformed or\nexpired token, `403` for a revoked key or a plan without API access. See the `Unauthorized`\nand `AuthForbidden` responses.\n"
      },
      "signupApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Internal-API-Key",
        "description": "Internal provisioning key used **only** by `POST /v2/auth/signup`, which creates\nbrand-new accounts and therefore cannot present a tenant Bearer token.\n\nThe header `X-Signup-Api-Key` is accepted as an alias when `X-Internal-API-Key`\nis absent. This credential is issued to internal gigstack systems and is not part\nof the public tenant API surface.\n"
      }
    },
    "parameters": {
      "TeamParameter": {
        "name": "team",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "**gigstack Connect:** Target team ID for multi-team access.\n\nRequires gigstack Connect enabled on your team and shared billing account.\n\nAlso requires the `multipleIssuerAccounts` feature on your plan. Requests targeting a\nteam other than the one your API key belongs to return `403` without it.\n\nOnly API keys can use it: an OAuth access token sent with another team's id is rejected with\n`403 Team mismatch with OAuth token`.\n\n**Optional — omit it entirely** unless you are acting on another team. It deliberately\ncarries no example value so generated snippets do not emit `?team=undefined`; when the\nparameter is absent, the team is derived from your API key.\n\n**Example:** `?team=team_xyz789`\n"
      },
      "LimitParam": {
        "name": "limit",
        "in": "query",
        "description": "Maximum number of items to return (default 10, max 100)",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 10
        }
      },
      "NextParam": {
        "name": "next",
        "in": "query",
        "description": "Pagination cursor for the next page of results",
        "required": false,
        "schema": {
          "type": "string",
          "nullable": true
        }
      },
      "OrderByParam": {
        "name": "order_by",
        "in": "query",
        "description": "Field name to order results by",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "name",
            "timestamp"
          ],
          "default": "timestamp"
        }
      },
      "SortParam": {
        "name": "sort",
        "in": "query",
        "description": "Sort direction for the results",
        "required": false,
        "schema": {
          "$ref": "#/components/schemas/OrderDirection"
        }
      },
      "CreatedGteParam": {
        "name": "created[gte]",
        "in": "query",
        "description": "Filter results created on or after this timestamp. Accepts Unix timestamp in seconds (e.g., 1733011200), milliseconds (e.g., 1733011200000), or ISO 8601 date string (e.g., 2024-12-01).",
        "required": false,
        "schema": {
          "oneOf": [
            {
              "type": "integer",
              "format": "int64"
            },
            {
              "type": "string",
              "format": "date"
            }
          ]
        }
      },
      "CreatedGtParam": {
        "name": "created[gt]",
        "in": "query",
        "description": "Filter results created after this timestamp. Accepts Unix timestamp in seconds (e.g., 1733011200), milliseconds (e.g., 1733011200000), or ISO 8601 date string (e.g., 2024-12-01).",
        "required": false,
        "schema": {
          "oneOf": [
            {
              "type": "integer",
              "format": "int64"
            },
            {
              "type": "string",
              "format": "date"
            }
          ]
        }
      },
      "CreatedLteParam": {
        "name": "created[lte]",
        "in": "query",
        "description": "Filter results created on or before this timestamp. Accepts Unix timestamp in seconds (e.g., 1735689599), milliseconds (e.g., 1735689599000), or ISO 8601 date string (e.g., 2024-12-31).",
        "required": false,
        "schema": {
          "oneOf": [
            {
              "type": "integer",
              "format": "int64"
            },
            {
              "type": "string",
              "format": "date"
            }
          ]
        }
      },
      "CreatedLtParam": {
        "name": "created[lt]",
        "in": "query",
        "description": "Filter results created before this timestamp. Accepts Unix timestamp in seconds (e.g., 1735689599), milliseconds (e.g., 1735689599000), or ISO 8601 date string (e.g., 2024-12-31).",
        "required": false,
        "schema": {
          "oneOf": [
            {
              "type": "integer",
              "format": "int64"
            },
            {
              "type": "string",
              "format": "date"
            }
          ]
        }
      },
      "FieldsParam": {
        "name": "fields",
        "in": "query",
        "description": "Comma-separated list of fields to include in the response",
        "required": false,
        "style": "form",
        "explode": false,
        "schema": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "PaymentStatusParam": {
        "name": "status",
        "in": "query",
        "description": "Filter payments by status",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "requires_payment_method",
            "succeeded",
            "partially_paid",
            "canceled"
          ]
        }
      },
      "PaymentCurrencyParam": {
        "name": "currency",
        "in": "query",
        "description": "Filter payments by currency code (e.g., MXN, USD)",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "PaymentClientIdParam": {
        "name": "client_id",
        "in": "query",
        "description": "Filter payments by client ID",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "PaymentEmailParam": {
        "name": "email",
        "in": "query",
        "description": "Filter payments by client email address",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "PaymentTaxIdParam": {
        "name": "tax_id",
        "in": "query",
        "description": "Filter payments by client tax ID (RFC)",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "PaymentClientNameParam": {
        "name": "client_name",
        "in": "query",
        "description": "Filter payments by client name",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "PaymentAmountParam": {
        "name": "amount",
        "in": "query",
        "description": "Filter payments by amount",
        "required": false,
        "schema": {
          "type": "number"
        }
      },
      "ClientIdFilterParam": {
        "name": "client_id",
        "in": "query",
        "description": "Filter results by the gigstack client ID (e.g., `client_xxx`)",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "TaxIdFilterParam": {
        "name": "tax_id",
        "in": "query",
        "description": "Filter results by the client's tax ID / RFC (e.g., `PEGJ800101ABC`)",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "SearchQueryParam": {
        "name": "q",
        "in": "query",
        "description": "Search query text (primary parameter). Searches across relevant fields depending on the collection\n(e.g., client name, email, payment ID, description, metadata). The `query` parameter is also accepted\nas a backward-compatible alternative.\n",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "SearchQueryBackwardCompatParam": {
        "name": "query",
        "in": "query",
        "description": "Alternative to `q`, kept for backward compatibility. If both are provided, `q` takes precedence.",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "SearchPageParam": {
        "name": "page",
        "in": "query",
        "description": "Page number for pagination (default 1)",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Authentication failed. Two different bodies can come back with a `401`:\n\n1. **From the authentication layer**, before the endpoint runs: a raw object with\n   `message` and — for OAuth access tokens only — `error` / `error_description`. It does\n   **not** use the standardized envelope (`success` and `timestamp` are absent). Messages:\n   `Unauthorized` (missing header, missing `Bearer ` prefix, unparseable token),\n   `Unauthorized, missing team in token`, `Unauthorized, not a master team` and\n   `Unauthorized, no matched teams` (gigstack Connect), `Invalid access token`,\n   `Access token has expired. Please refresh your token.`, `Access token has been revoked`.\n2. **From the endpoint itself**: the standardized envelope with `error.code: unauthorized`.\n\nBranch on the HTTP status, not on the body shape.\n",
        "content": {
          "application/json": {
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/AuthMiddlewareError"
                },
                {
                  "$ref": "#/components/schemas/UnauthorizedError"
                }
              ]
            },
            "examples": {
              "missing_or_invalid_key": {
                "summary": "Authentication layer — missing or unparseable API key",
                "value": {
                  "message": "Unauthorized"
                }
              },
              "oauth_token_expired": {
                "summary": "Authentication layer — expired OAuth access token",
                "value": {
                  "message": "Access token has expired. Please refresh your token.",
                  "error": "token_expired",
                  "error_description": "Access token has expired. Please refresh your token."
                }
              },
              "connect_not_master_team": {
                "summary": "Authentication layer — `team` sent by a team without gigstack Connect",
                "value": {
                  "message": "Unauthorized, not a master team"
                }
              },
              "endpoint_envelope": {
                "summary": "Endpoint — standardized envelope",
                "value": {
                  "success": false,
                  "error": {
                    "code": "unauthorized",
                    "message": "Unauthorized access"
                  },
                  "timestamp": 1767225600000
                }
              }
            }
          }
        }
      },
      "AuthForbidden": {
        "description": "Rejected by the authentication layer after the credential was recognised. The body is a raw\nobject (`message`, sometimes `details`), **not** the standardized envelope. Causes:\n\n- The API key was revoked or disabled: `message: \"API Key inválida.\"`, `details: \"Invalid API Key\"`.\n- The billing account's plan does not include API access. `message` is a Spanish sentence\n  containing an HTML link to `https://app.gigstack.pro/memberships`. Branch on the status\n  code; do not display or match the text.\n- gigstack Connect: the plan lacks the `multipleIssuerAccounts` feature (Spanish message\n  starting `Tu plan no incluye múltiples cuentas emisoras.`), or an OAuth access token was\n  sent with a `team` other than its own (`Team mismatch with OAuth token`).\n\nAn endpoint may also answer `403` for its own reasons; those are documented on the\noperation when they exist.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/AuthMiddlewareError"
            },
            "examples": {
              "revoked_api_key": {
                "summary": "API key revoked or disabled",
                "value": {
                  "message": "API Key inválida.",
                  "details": "Invalid API Key"
                }
              },
              "plan_without_api_access": {
                "summary": "Plan does not include API access",
                "value": {
                  "message": "La API se encuentra disponible para un plan más grande, por favor actualiza tu plan <a href='https://app.gigstack.pro/memberships'>aquí</a> o ponte en contacto con soporte."
                }
              },
              "connect_plan_without_multiple_issuers": {
                "summary": "gigstack Connect — plan lacks multipleIssuerAccounts",
                "value": {
                  "message": "Tu plan no incluye múltiples cuentas emisoras. Actualiza tu plan en https://app.gigstack.pro/memberships o ponte en contacto con soporte para operar sobre otros equipos."
                }
              },
              "oauth_team_mismatch": {
                "summary": "gigstack Connect — OAuth token used for another team",
                "value": {
                  "message": "Team mismatch with OAuth token"
                }
              }
            }
          }
        }
      },
      "ServerError": {
        "description": "Unexpected server error (`error.code: internal_server_error`). The failure is logged on gigstack's side.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/StandardErrorResponse"
            },
            "example": {
              "success": false,
              "error": {
                "code": "internal_server_error",
                "message": "An internal server error occurred"
              },
              "timestamp": 1767225600000
            }
          }
        }
      }
    },
    "schemas": {
      "AuthMiddlewareError": {
        "type": "object",
        "description": "Raw error body produced by the authentication layer (before any endpoint runs). It is not\nthe standardized envelope: there is no `success` and no `timestamp`.\n",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable reason. Some messages are in Spanish; branch on the HTTP status, not on this text.",
            "example": "Unauthorized"
          },
          "error": {
            "type": "string",
            "description": "OAuth error code. Present only when an OAuth access token was presented.",
            "enum": [
              "invalid_token",
              "token_expired",
              "token_revoked",
              "server_error"
            ],
            "example": "token_expired"
          },
          "error_description": {
            "type": "string",
            "description": "Same text as `message`. Present only alongside `error`.",
            "example": "Access token has expired. Please refresh your token."
          },
          "details": {
            "description": "Extra detail, e.g. `Invalid API Key` when a revoked key is rejected with `403`.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "example": "Invalid API Key"
          }
        }
      },
      "WebhookEventType": {
        "type": "string",
        "description": "Event type a webhook can subscribe to.",
        "enum": [
          "payment.created",
          "payment.updated",
          "payment.succeeded",
          "payment.canceled",
          "payment.deleted",
          "payment.upcoming_due_date",
          "invoice.created",
          "invoice.canceled",
          "invoice.failed",
          "invoice_batch.completed",
          "receipt.created",
          "receipt.updated",
          "receipt.completed",
          "receipt.deleted",
          "customer.created",
          "customer.updated",
          "customer.deleted",
          "service.created",
          "service.updated",
          "service.deleted",
          "sat.invoice.synced"
        ],
        "example": "sat.invoice.synced"
      },
      "WebhookCreated": {
        "description": "The created webhook, plus its signing secret. The secret is returned **only in this response**.",
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiPublicWebhook"
          },
          {
            "type": "object",
            "required": [
              "secret"
            ],
            "properties": {
              "secret": {
                "type": "string",
                "description": "HMAC-SHA256 signing secret for this webhook: 64 hexadecimal characters. gigstack uses\nthis string (as-is, as a UTF-8 key) to sign `sat.invoice.synced` and\n`invoice_batch.completed` deliveries in the `X-Gigstack-Signature` header. Resource\nevents (`payment.*`, `invoice.*`, `receipt.*`, `customer.*`, `service.*`) are **not**\nsigned with it.\n\n**Shown once.** It is never returned again by `GET`, `PUT` or list calls, and there is\nno endpoint to reveal or rotate it. If you lose it, delete the webhook and create a new one.\n",
                "example": "3f9a1c0e7b2d4f6a8c1e3b5d7f9a2c4e6b8d0f1a3c5e7b9d2f4a6c8e0b1d3f5a"
              }
            }
          }
        ]
      },
      "WebhookEventPayload": {
        "description": "Body of a webhook delivery (`Content-Type: application/json`). There are three formats:\n\n- **Resource events** (`payment.*`, `invoice.*`, `receipt.*`, `customer.*`, `service.*`) use the\n  webhook's payload version:\n  - `WebhookPayloadV1`: the default for webhooks created with `POST /webhooks`.\n  - `WebhookPayloadV2`: for webhooks created or last saved in the gigstack dashboard, or on teams\n    whose default is v2.\n- **`sat.invoice.synced`** always uses `SatInvoiceSyncedWebhookEvent`.\n- **`invoice_batch.completed`** always uses `InvoiceBatchCompletedWebhookEvent`.\n\nTell them apart by shape:\n- v2 has `type` and `data.object`.\n- v1 has `event`, `team` and `webhook`.\n- The SAT and batch events have `event` and `created_at`; read `event` to tell them apart.\n",
        "oneOf": [
          {
            "$ref": "#/components/schemas/WebhookPayloadV1"
          },
          {
            "$ref": "#/components/schemas/WebhookPayloadV2"
          },
          {
            "$ref": "#/components/schemas/SatInvoiceSyncedWebhookEvent"
          },
          {
            "$ref": "#/components/schemas/InvoiceBatchCompletedWebhookEvent"
          }
        ]
      },
      "WebhookPayloadV1": {
        "type": "object",
        "description": "`v1` body of a resource event. It has no event id, so de-duplicate on `event` plus `data.id`.\n\nTeams on the legacy `v1.1` default receive this object wrapped as `{ \"payload\": { … } }`. For\n`invoice.created`, their `data` also includes a `customer` object with the full address, and\n`date` is shifted by −6 hours.\n",
        "required": [
          "event",
          "team",
          "webhook",
          "livemode",
          "data"
        ],
        "properties": {
          "event": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "team": {
            "type": "string",
            "description": "Team that owns the webhook.",
            "example": "team_1234567890"
          },
          "webhook": {
            "type": "string",
            "description": "ID of the webhook receiving this delivery.",
            "example": "wh_dyS2ZVTj"
          },
          "livemode": {
            "type": "boolean",
            "description": "`false` for test-mode resources.",
            "example": true
          },
          "data": {
            "type": "object",
            "description": "The resource at the moment of the event, in gigstack's internal (camelCase) format.\n`metadata` values are sent as strings.\n",
            "additionalProperties": true
          },
          "connectedTeam": {
            "type": "string",
            "description": "Only on deliveries to a gigstack Connect master team. The connected team the event came from."
          },
          "connectedTeamMetadata": {
            "type": "object",
            "description": "Only with `connectedTeam`, when that team has metadata. Values are strings.",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "WebhookPayloadV2": {
        "type": "object",
        "description": "`v2` body of a resource event (Stripe-style envelope).",
        "required": [
          "id",
          "type",
          "created",
          "livemode",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique per event and webhook. Stays the same across every retry and resend of that delivery,\nso use it to de-duplicate.\n",
            "example": "log_4GqT7mZx9LpR2vWc8NdK--wh_dyS2ZVTj"
          },
          "type": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "created": {
            "type": "integer",
            "format": "int64",
            "description": "When the delivery was queued, Unix epoch **milliseconds**.",
            "example": 1767225600000
          },
          "livemode": {
            "type": "boolean",
            "description": "`false` for test-mode resources.",
            "example": true
          },
          "data": {
            "type": "object",
            "required": [
              "object"
            ],
            "properties": {
              "object": {
                "type": "object",
                "description": "The resource in the same format the API returns. It is read when the delivery is sent,\nso a retried delivery can show a newer state than the event. For `*.deleted` events it\nis the last known state.\n",
                "additionalProperties": true
              }
            }
          }
        }
      },
      "SatInvoiceSyncedWebhookEvent": {
        "type": "object",
        "description": "Body of a `sat.invoice.synced` delivery. It is the same regardless of the webhook's payload version.\nNote the field names: the type is in `event` (not `type`), and `created_at` is in **seconds**.\nThere is no `livemode`.\n",
        "required": [
          "id",
          "event",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique event id, `evt_` followed by 16 hexadecimal characters. Use it to de-duplicate.",
            "example": "evt_4f1c9a7e2b3d5c6a"
          },
          "event": {
            "type": "string",
            "enum": [
              "sat.invoice.synced"
            ],
            "example": "sat.invoice.synced"
          },
          "created_at": {
            "type": "integer",
            "description": "When the event was dispatched, Unix epoch **seconds**.",
            "example": 1767225600
          },
          "data": {
            "$ref": "#/components/schemas/SatInvoiceSyncedWebhookData"
          }
        }
      },
      "SatInvoiceSyncedWebhookData": {
        "type": "object",
        "description": "`data` of a `sat.invoice.synced` delivery. Sent when the XML of an invoice downloaded from the\nSAT (Descarga Masiva) has been fetched and stored, either by the automatic download or by\n`POST /invoices/sat/{uuid}/retry-xml`.\n",
        "required": [
          "uuid",
          "resource_status",
          "team"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Folio fiscal (UUID) of the CFDI.",
            "example": "9D9B0E5B-0341-4C2B-8F3A-6E1D2C4B5A70"
          },
          "direction": {
            "type": "string",
            "enum": [
              "issued",
              "received"
            ],
            "description": "Whether your team issued or received the CFDI.",
            "example": "received"
          },
          "resource_status": {
            "type": "string",
            "enum": [
              "ready"
            ],
            "description": "Always `ready` — the XML is stored and the invoice can be read.",
            "example": "ready"
          },
          "issuer": {
            "type": "object",
            "description": "Issuer of the CFDI, as stored for the SAT invoice.",
            "additionalProperties": true,
            "example": {
              "rfc": "EKU9003173C9",
              "name": "ESCUELA KEMPER URGATE"
            }
          },
          "receiver": {
            "type": "object",
            "description": "Receiver of the CFDI, as stored for the SAT invoice.",
            "additionalProperties": true,
            "example": {
              "rfc": "MEE200101ABC",
              "name": "MI EMPRESA EJEMPLO"
            }
          },
          "total": {
            "type": "number",
            "description": "CFDI total.",
            "example": 1160
          },
          "currency": {
            "type": "string",
            "example": "MXN"
          },
          "issue_date": {
            "type": "string",
            "description": "CFDI issue date as stored for the SAT invoice.",
            "example": "2026-01-15T10:30:00"
          },
          "invoice_type": {
            "type": "string",
            "enum": [
              "I",
              "E",
              "P",
              "N",
              "T"
            ],
            "description": "SAT comprobante type.",
            "example": "I"
          },
          "status": {
            "type": "string",
            "description": "SAT status of the CFDI.",
            "example": "Vigente"
          },
          "team": {
            "type": "string",
            "description": "Team that owns the invoice.",
            "example": "team_1234567890"
          },
          "credit_charged": {
            "type": "boolean",
            "description": "Whether a Descarga Masiva credit was charged for this XML.",
            "example": true
          },
          "retried": {
            "type": "boolean",
            "description": "Present and `true` only when the delivery was triggered by `POST /invoices/sat/{uuid}/retry-xml`.",
            "example": true
          }
        }
      },
      "InvoiceBatchCompletedWebhookEvent": {
        "type": "object",
        "description": "Body of an `invoice_batch.completed` delivery, sent once when every accepted item of an income invoice\nbatch (`POST /invoices/income/batch`) has a final status. It is the same regardless of the webhook's\npayload version. As with `sat.invoice.synced`, the type is in `event` (not `type`) and `created_at`\nis in **seconds**. A batch whose items were all rejected up front completes without any stamping and\nalso sends this event.\n",
        "required": [
          "id",
          "event",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique event id, `evt_` followed by 16 hexadecimal characters. Use it to de-duplicate.",
            "example": "evt_9a2b7c4d1e6f3a8b"
          },
          "event": {
            "type": "string",
            "enum": [
              "invoice_batch.completed"
            ],
            "example": "invoice_batch.completed"
          },
          "created_at": {
            "type": "integer",
            "description": "When the event was dispatched, Unix epoch **seconds**.",
            "example": 1790784000
          },
          "data": {
            "$ref": "#/components/schemas/InvoiceBatchCompletedWebhookData"
          }
        }
      },
      "InvoiceBatchCompletedWebhookData": {
        "type": "object",
        "description": "Summary of the finished batch. It carries counts only: to see each invoice, page through\n`GET /invoices/income/batch/{id}/items`; for the rejected items' reasons, read `rejected` on\n`GET /invoices/income/batch/{id}`.\n",
        "required": [
          "id",
          "livemode",
          "total",
          "accepted",
          "rejected",
          "counts",
          "result"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Batch id, as returned by `POST /invoices/income/batch`.",
            "example": "ibatch_5d41402abc4b2a76b9719d911017c592"
          },
          "livemode": {
            "type": "boolean",
            "description": "Mode of the credential that created the batch.",
            "example": true
          },
          "total": {
            "type": "integer",
            "description": "Invoices in the request.",
            "example": 250
          },
          "accepted": {
            "type": "integer",
            "description": "Invoices that passed validation and were processed.",
            "example": 248
          },
          "rejected": {
            "type": "integer",
            "description": "**Number** of invoices refused by validation before anything was stamped. Note that on the batch\nobject `rejected` is the list of those items, not a count.\n",
            "example": 2
          },
          "counts": {
            "$ref": "#/components/schemas/InvoiceBatchCounts"
          },
          "result": {
            "$ref": "#/components/schemas/InvoiceBatchResultEnum"
          }
        }
      },
      "SatInvoice": {
        "type": "object",
        "description": "An invoice downloaded from SAT via Descarga Masiva",
        "properties": {
          "id": {
            "type": "string",
            "description": "Document ID (same as UUID)"
          },
          "uuid": {
            "type": "string",
            "description": "SAT UUID (globally unique CFDI identifier)",
            "example": "6741A863-04BE-49FE-BB76-E1657AB6B7EA"
          },
          "direction": {
            "type": "string",
            "enum": [
              "issued",
              "received"
            ],
            "description": "Whether this RFC issued or received the invoice"
          },
          "issuer": {
            "type": "object",
            "properties": {
              "rfc": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "receiver": {
            "type": "object",
            "properties": {
              "rfc": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "invoice_type": {
            "type": "string",
            "enum": [
              "I",
              "E",
              "P",
              "N",
              "T"
            ],
            "description": "CFDI type (I=Income, E=Egress, P=Payment, N=Nomina, T=Transfer)"
          },
          "series": {
            "type": "string",
            "nullable": true
          },
          "folio": {
            "type": "string",
            "nullable": true
          },
          "subtotal": {
            "type": "number"
          },
          "total": {
            "type": "number"
          },
          "currency": {
            "type": "string",
            "example": "MXN"
          },
          "exchange_rate": {
            "type": "number",
            "nullable": true
          },
          "issue_date": {
            "type": "string",
            "description": "Issue date (YYYY-MM-DD or datetime from SAT)"
          },
          "stamp_date": {
            "type": "string",
            "description": "Timestamp when PAC stamped the CFDI"
          },
          "cancellation_date": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "Vigente",
              "Cancelado"
            ]
          },
          "pac_rfc": {
            "type": "string",
            "description": "RFC of the PAC that stamped the invoice"
          },
          "version": {
            "type": "string",
            "example": "4.0"
          },
          "certificate_number": {
            "type": "string"
          },
          "download_request_id": {
            "type": "string",
            "nullable": true,
            "description": "ID of the satreq_ document that downloaded this invoice"
          },
          "has_xml": {
            "type": "boolean",
            "description": "Whether the XML has been downloaded and stored"
          },
          "created_at": {
            "type": "integer",
            "description": "Unix timestamp (ms) when first downloaded"
          },
          "updated_at": {
            "type": "integer",
            "description": "Unix timestamp (ms) of last update"
          }
        }
      },
      "OrderDirection": {
        "type": "string",
        "enum": [
          "asc",
          "desc"
        ],
        "description": "Sort direction for list queries"
      },
      "ApiPublicProductKey": {
        "type": "object",
        "required": [
          "code",
          "description"
        ],
        "properties": {
          "code": {
            "type": "string",
            "example": "81112101",
            "description": "SAT product/service key (c_ClaveProdServ). Use this value as an item's product_key."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Servicios de programación de aplicaciones",
            "description": "Official SAT description of the key"
          },
          "similar": {
            "type": "string",
            "example": "desarrollo de software, programación",
            "description": "Synonyms published by the SAT. Omitted when the entry has none."
          },
          "type": {
            "type": "string",
            "example": "Clase",
            "description": "SAT taxonomy level. Omitted when the entry has none."
          },
          "division": {
            "type": "string",
            "example": "Servicios de Tecnologías de la Información",
            "description": "SAT taxonomy division. Omitted when the entry has none."
          },
          "group": {
            "type": "string",
            "example": "Servicios de programación informática",
            "description": "SAT taxonomy group. Omitted when the entry has none."
          }
        }
      },
      "ApiPublicUnitKey": {
        "type": "object",
        "required": [
          "code",
          "name"
        ],
        "properties": {
          "code": {
            "type": "string",
            "example": "E48",
            "description": "SAT unit key (c_ClaveUnidad). Use this value as an item's unit_key."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "example": "Unidad de servicio",
            "description": "Human-readable unit name. Commonly stored alongside the key as unit_name."
          }
        }
      },
      "ApiPublicClient": {
        "type": "object",
        "required": [
          "id",
          "email",
          "from",
          "livemode",
          "owner",
          "team",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "client_1234567890",
            "description": "Unique client identifier"
          },
          "address": {
            "$ref": "#/components/schemas/ClientAddress"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "example": "Juan Pérez García",
            "description": "Client name"
          },
          "company": {
            "type": "string",
            "nullable": true,
            "example": "Empresa SA de CV",
            "description": "Client company name"
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "example": "+52 55 1234 5678",
            "description": "Client phone number"
          },
          "email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "example": "juan.perez@ejemplo.com",
            "description": "Client email address"
          },
          "bcc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            },
            "nullable": true,
            "example": [
              "admin@empresa.com"
            ],
            "description": "BCC email addresses for client communications"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "example": {
              "custom_field": "value"
            },
            "description": "Additional metadata for the client"
          },
          "is_valid": {
            "type": "boolean",
            "nullable": true,
            "example": true,
            "description": "Whether the client data is valid"
          },
          "from": {
            "type": "string",
            "example": "api",
            "description": "Source of client creation. Documents created through the public API are stored with `api`; requests carrying the `X-Gigstack-Client: mcp` header (the gigstack MCP server) are stored with `mcp` and behave identically."
          },
          "legal_name": {
            "type": "string",
            "nullable": true,
            "example": "Juan Pérez García",
            "description": "Legal name for tax purposes"
          },
          "livemode": {
            "type": "boolean",
            "example": true,
            "description": "Whether this client is in live mode"
          },
          "owner": {
            "type": "string",
            "example": "user_1234567890",
            "description": "User ID who owns this client"
          },
          "tax_id": {
            "type": "string",
            "nullable": true,
            "example": "PEGJ800101ABC",
            "description": "RFC (Tax ID) for Mexican tax compliance"
          },
          "use": {
            "type": "string",
            "nullable": true,
            "example": "G03",
            "description": "CFDI use code"
          },
          "tax_system": {
            "type": "string",
            "nullable": true,
            "example": "601",
            "description": "SAT tax system code"
          },
          "team": {
            "type": "string",
            "example": "team_1234567890",
            "description": "Team ID this client belongs to"
          },
          "created_at": {
            "type": "number",
            "example": 1677651234,
            "description": "Unix timestamp of client creation"
          },
          "efos": {
            "type": "object",
            "nullable": true,
            "properties": {
              "is_valid": {
                "type": "boolean",
                "nullable": true,
                "example": true,
                "description": "true = RFC is NOT on the EFOS (Art. 69-B) blacklist (safe). false = RFC appears on the blacklist."
              }
            },
            "description": "EFOS (Art. 69-B CFF) blacklist check. Independent from `fiscal_validation` — an RFC can fail one and pass the other."
          },
          "fiscal_validation": {
            "type": "object",
            "nullable": true,
            "description": "Result of attempting to stamp a test CFDI against the PAC. Only returned on create/update/validate; not persisted on the client doc.",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "valid",
                  "not_valid",
                  "skipped"
                ],
                "example": "not_valid",
                "description": "`valid` = PAC accepted; `not_valid` = PAC rejected (RFC/legal_name/CP do not match SAT registry); `skipped` = required fields missing."
              },
              "message": {
                "type": "string",
                "nullable": true,
                "example": "Fiscal info validation failed. El campo DomicilioFiscalReceptor del receptor, debe pertenecer al nombre asociado al RFC registrado en el campo Rfc del Receptor.",
                "description": "Human-readable reason when status is not_valid or skipped."
              }
            }
          },
          "sat_status": {
            "type": "object",
            "nullable": true,
            "description": "Unified SAT risk signal combining the EFOS check with 20 SAT Datos Abiertos lists (Art. 69, 69-B, 69-B Bis)\nsynced weekly into Firestore. A hit on any \"risky\" list (Cancelados, No localizados, CSD sin efectos, Definitivos 69-B,\nPresuntos 69-B, etc.) or a failed EFOS check sets `is_risky: true`.\n",
            "properties": {
              "is_risky": {
                "type": "boolean",
                "example": true,
                "description": "true if any risky list hit OR `efos.is_valid === false`."
              },
              "efos": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "is_valid": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  }
                },
                "description": "EFOS check result (duplicated here for convenience)."
              },
              "hits": {
                "type": "array",
                "description": "Every SAT list the RFC appears on, with the full row from the source CSV.",
                "items": {
                  "type": "object",
                  "properties": {
                    "list": {
                      "type": "string",
                      "example": "art_69b_definitivos",
                      "description": "List key (matches the source filename). See /sat_rfc_list_entries for all."
                    },
                    "label": {
                      "type": "string",
                      "example": "Definitivos 69-B"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "art_69",
                        "art_69b",
                        "art_69b_bis"
                      ],
                      "example": "art_69b"
                    },
                    "is_risky": {
                      "type": "boolean",
                      "example": true,
                      "description": "Whether a hit on this specific list marks the RFC unsafe."
                    },
                    "detail": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "Full SAT record (razón social, situación, dates, oficios DOF, etc.). Shape varies per list."
                    }
                  }
                }
              },
              "checked_at": {
                "type": "number",
                "example": 1776887458784,
                "description": "Unix timestamp (ms) of when this check was run."
              }
            }
          },
          "defaults": {
            "type": "object",
            "nullable": true,
            "properties": {
              "keep_full_legal_name": {
                "type": "boolean",
                "nullable": true,
                "example": false,
                "description": "Keep full legal name in documents"
              },
              "issue_automatic_invoices": {
                "type": "boolean",
                "nullable": true,
                "example": false,
                "description": "Issue automatic invoices"
              },
              "issue_invoiceable_receipts": {
                "type": "boolean",
                "nullable": true,
                "example": true,
                "description": "Issue invoiceable receipts"
              }
            },
            "description": "Client default settings"
          },
          "document_type": {
            "type": "string",
            "nullable": true,
            "description": "Colombia (DIAN) only: identification document code (`11`, `12`, `13`, `21`, `22`, `31`, `41`, `42`, `47`, `48`, `50`, `91`)."
          },
          "organization_type": {
            "anyOf": [
              {
                "description": "Colombia (DIAN) only: `1` legal entity, `2` natural person.",
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string"
                  }
                ]
              },
              {
                "type": "object",
                "nullable": true,
                "enum": [
                  null
                ]
              }
            ]
          },
          "tribute_code": {
            "type": "string",
            "nullable": true,
            "description": "Colombia (DIAN) only: `01` IVA responsible, `ZZ` not applicable."
          },
          "fiscal_responsibilities": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "description": "Colombia (DIAN) only: fiscal responsibilities (list 53), e.g. `O-13`, `R-99-PN`."
          },
          "dv": {
            "type": "string",
            "nullable": true,
            "description": "Colombia (DIAN) only: NIT verification digit (informational)."
          },
          "municipality_code": {
            "type": "string",
            "nullable": true,
            "description": "Colombia (DIAN) only: 5-digit DANE municipality code."
          }
        }
      },
      "ApiPublicService": {
        "type": "object",
        "required": [
          "team",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "nullable": true,
            "example": "service_1234567890",
            "description": "Unique service identifier"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Consulting services",
            "description": "Service description"
          },
          "from": {
            "type": "string",
            "nullable": true,
            "example": "api",
            "description": "Source of service creation. Documents created through the public API are stored with `api`; requests carrying the `X-Gigstack-Client: mcp` header (the gigstack MCP server) are stored with `mcp` and behave identically."
          },
          "sku": {
            "type": "string",
            "nullable": true,
            "example": "CONS-001",
            "description": "Stock Keeping Unit identifier"
          },
          "product_key": {
            "type": "string",
            "nullable": true,
            "example": "80141503",
            "description": "SAT product key for tax compliance"
          },
          "unit_key": {
            "type": "string",
            "nullable": true,
            "example": "E48",
            "description": "SAT unit key for tax compliance"
          },
          "unit_name": {
            "type": "string",
            "nullable": true,
            "example": "Servicio",
            "description": "Unit name for the service"
          },
          "unit_price": {
            "type": "number",
            "nullable": true,
            "example": 1000,
            "description": "Price per unit"
          },
          "taxes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaxElement"
            },
            "nullable": true,
            "description": "Tax configuration for this service"
          },
          "team": {
            "type": "string",
            "example": "team_1234567890",
            "description": "Team ID this service belongs to"
          },
          "created_at": {
            "type": "number",
            "example": 1677651234,
            "description": "Unix timestamp of service creation"
          },
          "quantity": {
            "type": "number",
            "nullable": true,
            "example": 1,
            "description": "Quantity (used in transactions)"
          },
          "discount": {
            "type": "number",
            "nullable": true,
            "description": "Discount applied to the item."
          },
          "third_party": {
            "type": "object",
            "nullable": true,
            "description": "Third party on whose behalf the item is billed (A cuenta de terceros).",
            "properties": {
              "legal_name": {
                "type": "string"
              },
              "tax_id": {
                "type": "string"
              },
              "tax_system": {
                "type": "string"
              },
              "zip": {
                "type": "string"
              }
            }
          },
          "item_complement": {
            "type": "object",
            "nullable": true,
            "description": "Item-level CFDI complement, when configured."
          }
        }
      },
      "PendingReceiptsSummary": {
        "type": "object",
        "description": "Summary of pending-receipt invoicing attempts triggered by a client update.",
        "properties": {
          "attempted": {
            "type": "integer",
            "description": "Number of pending receipts that were submitted for invoicing.",
            "example": 3
          },
          "succeeded": {
            "type": "integer",
            "description": "Number of receipts successfully invoiced.",
            "example": 2
          },
          "failed": {
            "type": "integer",
            "description": "Number of receipts that failed to invoice.",
            "example": 1
          },
          "skipped": {
            "type": "integer",
            "description": "Number of receipts skipped (e.g., `disallowInvoice: true`).",
            "example": 0
          },
          "failures": {
            "type": "array",
            "description": "Per-receipt failure details.",
            "items": {
              "type": "object",
              "properties": {
                "receipt_id": {
                  "type": "string",
                  "example": "receipt_1234567890"
                },
                "error": {
                  "type": "string",
                  "example": "Failed to process receipt: 400 Bad Request"
                }
              }
            }
          }
        }
      },
      "ClientInput": {
        "description": "Creation body for `POST /v2/clients`. `name` is required when creating a client.\nFor `PUT /v2/clients/{id}`, use `ClientUpdateInput`: an omitted name is preserved\nfrom the existing client before validation.\n\nUnknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`);\n`metadata` is the one object that accepts arbitrary keys. `team`, `livemode` and\n`owner` are reserved and injected by the auth middleware.\n\nThe `document_type`, `organization_type`, `tribute_code`, `fiscal_responsibilities`,\n`dv` and `municipality_code`\nfields are the Colombian DIAN identification set. They are accepted for every team\nregardless of country; each also accepts the empty string, which means \"not set\" and is\ndropped before the client is stored.\n",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "search": {
            "description": "Search for an existing client before creating. If a match is found, the existing client is returned (or updated if `update: true`).\nThis enables upsert-like behavior to avoid duplicate clients.\n",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "on_key",
              "on_value"
            ],
            "properties": {
              "on_key": {
                "description": "The field to search on (e.g., 'tax_id', 'email', 'name')",
                "example": "tax_id",
                "type": "string"
              },
              "on_value": {
                "description": "The value to match against the specified field",
                "example": "PEGJ800101ABC",
                "type": "string"
              },
              "auto_create": {
                "type": "boolean",
                "nullable": true
              },
              "safety_check": {
                "type": "boolean",
                "nullable": true
              },
              "update": {
                "description": "If true and a match is found, update the existing client with the provided data. If false, return the existing client without modifications.",
                "example": false,
                "type": "boolean",
                "nullable": true
              }
            },
            "nullable": true
          },
          "address": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "country": {
                "example": "MEX",
                "type": "string",
                "nullable": true,
                "maxLength": 3
              },
              "street": {
                "example": "Av. Insurgentes Sur",
                "type": "string",
                "nullable": true
              },
              "zip": {
                "example": "03100",
                "type": "string",
                "nullable": true
              },
              "city": {
                "example": "Ciudad de México",
                "type": "string",
                "nullable": true
              },
              "state": {
                "example": "CDMX",
                "type": "string",
                "nullable": true
              },
              "exterior": {
                "example": "123",
                "type": "string",
                "nullable": true
              },
              "interior": {
                "example": "4B",
                "type": "string",
                "nullable": true
              },
              "municipality": {
                "example": "Benito Juárez",
                "type": "string",
                "nullable": true
              },
              "neighborhood": {
                "example": "Del Valle",
                "type": "string",
                "nullable": true
              }
            },
            "nullable": true
          },
          "name": {
            "example": "Juan Pérez García",
            "type": "string"
          },
          "company": {
            "example": "Empresa SA de CV",
            "type": "string",
            "nullable": true
          },
          "phone": {
            "example": "+52 55 1234 5678",
            "type": "string",
            "nullable": true
          },
          "email": {
            "example": "juan.perez@ejemplo.com",
            "type": "string",
            "nullable": true,
            "format": "email"
          },
          "bcc": {
            "example": [
              "admin@empresa.com"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "metadata": {
            "example": {
              "custom_field": "value"
            },
            "type": "object",
            "additionalProperties": true,
            "properties": {}
          },
          "legal_name": {
            "example": "Juan Pérez García",
            "type": "string",
            "nullable": true
          },
          "tax_id": {
            "example": "PEGJ800101ABC",
            "type": "string",
            "nullable": true
          },
          "use": {
            "example": "G03",
            "type": "string",
            "nullable": true
          },
          "tax_system": {
            "example": "601",
            "type": "string",
            "nullable": true
          },
          "defaults": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "keep_full_legal_name": {
                "example": false,
                "type": "boolean"
              },
              "issue_automatic_invoices": {
                "example": false,
                "type": "boolean"
              },
              "issue_invoiceable_receipts": {
                "example": true,
                "type": "boolean"
              }
            }
          },
          "document_type": {
            "description": "**Colombia (DIAN).** Identification document code.\n`11` registro civil, `12` tarjeta de identidad, `13` cédula de ciudadanía,\n`21` tarjeta de extranjería, `22` cédula de extranjería, `31` NIT,\n`41` pasaporte, `42` documento de identificación extranjero,\n`47` PEP, `48` PPT, `50` NIT de otro país, `91` NUIP.\nThe empty string means \"not set\" and is dropped before the client is stored.\n",
            "example": "31",
            "type": "string",
            "enum": [
              "",
              "11",
              "12",
              "13",
              "21",
              "22",
              "31",
              "41",
              "42",
              "47",
              "48",
              "50",
              "91",
              null
            ],
            "nullable": true
          },
          "organization_type": {
            "description": "**Colombia (DIAN).** `1` = persona jurídica, `2` = persona natural.\nAccepted as either a number (`1`, `2`) or a string (`\"1\"`, `\"2\"`).\nThe empty string means \"not set\".\n",
            "example": "2",
            "oneOf": [
              {
                "type": "string",
                "enum": [
                  "",
                  "1",
                  "2",
                  null
                ],
                "nullable": true
              },
              {
                "type": "number",
                "enum": [
                  1,
                  2
                ]
              }
            ]
          },
          "tribute_code": {
            "description": "**Colombia (DIAN).** `01` = responsable de IVA, `ZZ` = no aplica.\nThe empty string means \"not set\".\n",
            "example": "01",
            "type": "string",
            "enum": [
              "",
              "01",
              "ZZ",
              null
            ],
            "nullable": true
          },
          "fiscal_responsibilities": {
            "description": "**Colombia (DIAN).** Responsabilidades fiscales del cliente (lista 53).\n`O-13` gran contribuyente, `O-15` autorretenedor,\n`O-23` agente de retención de IVA, `O-47` régimen simple de tributación,\n`R-99-PN` no responsable.\nOmit the field (or send an empty array) to leave it unset — the client is\nthen reported as `R-99-PN`, which is also the value that applies when the\narray carries only that code. `R-99-PN` excludes every `O-*` code: if both\nare sent, only the `O-*` ones are reported.\n",
            "example": [
              "O-15",
              "O-23"
            ],
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "O-13",
                "O-15",
                "O-23",
                "O-47",
                "R-99-PN"
              ]
            },
            "nullable": true
          },
          "dv": {
            "description": "**Colombia (DIAN).** NIT verification digit — a single digit, or the empty\nstring for \"not set\".\n",
            "example": "7",
            "type": "string",
            "nullable": true,
            "pattern": "^[0-9]?$"
          },
          "municipality_code": {
            "description": "**Colombia (DIAN).** DANE municipality code — exactly five digits, or the empty\nstring for \"not set\". Only meaningful for clients domiciled in Colombia.\n",
            "example": "05001",
            "type": "string",
            "nullable": true,
            "pattern": "^([0-9]{5})?$"
          },
          "check_pending_receipts": {
            "description": "Only applies to `PUT /clients/{id}`. When `true` (default) and the updated client passes fiscal validation, all of the client's pending receipts are automatically invoiced using the new client data. Set to `false` to skip this behavior.\n",
            "example": true,
            "default": true,
            "type": "boolean"
          }
        }
      },
      "ServiceInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`) — body\nvalidation runs in strict allowlist mode. `team`, `livemode` and `owner` are reserved\nand injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "description": {
            "example": "Consulting services",
            "type": "string",
            "nullable": true
          },
          "sku": {
            "example": "CONS-001",
            "type": "string",
            "nullable": true
          },
          "product_key": {
            "example": "80141503",
            "type": "string",
            "nullable": true
          },
          "unit_key": {
            "example": "E48",
            "type": "string",
            "nullable": true
          },
          "unit_name": {
            "example": "Servicio",
            "type": "string",
            "nullable": true
          },
          "unit_price": {
            "example": 1000,
            "type": "number",
            "nullable": true
          },
          "taxes": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "base": {
                  "description": "Taxable base amount. Accepts number or numeric string. If null, calculated automatically from item price.",
                  "example": 100,
                  "oneOf": [
                    {
                      "type": "number",
                      "nullable": true
                    },
                    {
                      "type": "string",
                      "description": "Numeric string accepted by the request validator."
                    }
                  ]
                },
                "factor": {
                  "example": "Tasa",
                  "type": "string",
                  "nullable": true
                },
                "inclusive": {
                  "example": false,
                  "type": "boolean",
                  "nullable": true
                },
                "rate": {
                  "example": 0.16,
                  "type": "number",
                  "nullable": true
                },
                "type": {
                  "example": "IVA",
                  "type": "string",
                  "enum": [
                    "IVA",
                    "ISR",
                    "IEPS",
                    null
                  ],
                  "nullable": true
                },
                "withholding": {
                  "example": false,
                  "type": "boolean",
                  "nullable": true
                }
              },
              "nullable": true
            }
          },
          "item_complement": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "hydrocarbons": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "permit_type",
                  "permit_number",
                  "fuel_code",
                  "fuel_sub_product"
                ],
                "properties": {
                  "permit_type": {
                    "type": "string"
                  },
                  "permit_number": {
                    "type": "string"
                  },
                  "fuel_code": {
                    "type": "string"
                  },
                  "fuel_sub_product": {
                    "type": "string"
                  }
                },
                "nullable": true
              }
            },
            "nullable": true
          }
        }
      },
      "CfdiError": {
        "type": "object",
        "required": [
          "code",
          "description",
          "explanation",
          "solution",
          "type"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Unique CFDI error code identifier",
            "example": "CFDI140223"
          },
          "description": {
            "type": "string",
            "description": "Brief description of the error (typically in Spanish as provided by SAT)",
            "example": "El campo Rfc del receptor no es valido"
          },
          "explanation": {
            "type": "string",
            "description": "Detailed explanation of why this error occurs",
            "example": "The RFC (tax ID) provided for the receiver does not meet the validation requirements or format specified by SAT"
          },
          "solution": {
            "type": "string",
            "description": "Actionable steps to resolve the error",
            "example": "Verify that the receiver's RFC is correct, properly formatted (13 characters for individuals, 12 for legal entities), and matches SAT's registered information"
          },
          "type": {
            "type": "string",
            "enum": [
              "invoice",
              "receiver",
              "sender",
              "unknown"
            ],
            "description": "Category of the error",
            "example": "receiver"
          }
        }
      },
      "DraftInvoiceInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`) — body\nvalidation runs in strict allowlist mode. `team`, `livemode` and `owner` are reserved\nand injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "invoice_type"
        ],
        "properties": {
          "invoice_type": {
            "description": "Type of invoice to draft:\n- `I`: Income (Ingreso)\n- `E`: Egress (Egreso / Credit Note)\n",
            "example": "I",
            "type": "string",
            "enum": [
              "I",
              "E"
            ]
          },
          "client": {
            "description": "Client information (optional at creation, required for stamping)",
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "id": {
                "example": "client_1234567890",
                "type": "string",
                "nullable": true
              },
              "search": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "on_key",
                  "on_value"
                ],
                "properties": {
                  "on_key": {
                    "example": "tax_id",
                    "type": "string"
                  },
                  "on_value": {
                    "example": "PEGJ800101ABC",
                    "type": "string"
                  },
                  "auto_create": {
                    "example": true,
                    "type": "boolean",
                    "nullable": true
                  },
                  "safety_check": {
                    "type": "boolean",
                    "nullable": true
                  },
                  "update": {
                    "type": "boolean",
                    "nullable": true
                  }
                },
                "nullable": true
              },
              "address": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "country": {
                    "example": "MEX",
                    "type": "string",
                    "nullable": true,
                    "maxLength": 3
                  },
                  "street": {
                    "example": "Av. Insurgentes Sur",
                    "type": "string",
                    "nullable": true
                  },
                  "zip": {
                    "example": "03100",
                    "type": "string",
                    "nullable": true
                  },
                  "city": {
                    "example": "Ciudad de México",
                    "type": "string",
                    "nullable": true
                  },
                  "state": {
                    "example": "CDMX",
                    "type": "string",
                    "nullable": true
                  },
                  "exterior": {
                    "example": "123",
                    "type": "string",
                    "nullable": true
                  },
                  "interior": {
                    "example": "4B",
                    "type": "string",
                    "nullable": true
                  },
                  "municipality": {
                    "example": "Benito Juárez",
                    "type": "string",
                    "nullable": true
                  },
                  "neighborhood": {
                    "example": "Del Valle",
                    "type": "string",
                    "nullable": true
                  }
                },
                "nullable": true
              },
              "name": {
                "type": "string",
                "nullable": true
              },
              "company": {
                "type": "string",
                "nullable": true
              },
              "phone": {
                "type": "string",
                "nullable": true
              },
              "email": {
                "type": "string",
                "nullable": true
              },
              "bcc": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "metadata": {
                "type": "object",
                "additionalProperties": true,
                "properties": {}
              },
              "legal_name": {
                "type": "string",
                "nullable": true
              },
              "tax_id": {
                "type": "string",
                "nullable": true
              },
              "use": {
                "type": "string",
                "nullable": true
              },
              "tax_system": {
                "type": "string",
                "nullable": true
              },
              "document_type": {
                "description": "DIAN identification document code",
                "type": "string",
                "enum": [
                  "",
                  "11",
                  "12",
                  "13",
                  "21",
                  "22",
                  "31",
                  "41",
                  "42",
                  "47",
                  "48",
                  "50",
                  "91",
                  null
                ],
                "nullable": true
              },
              "organization_type": {
                "description": "1 = persona jurídica, 2 = persona natural",
                "oneOf": [
                  {
                    "type": "string",
                    "enum": [
                      "",
                      "1",
                      "2",
                      null
                    ],
                    "nullable": true
                  },
                  {
                    "type": "number",
                    "enum": [
                      1,
                      2
                    ]
                  }
                ]
              },
              "tribute_code": {
                "description": "'01' = responsable de IVA, 'ZZ' = no aplica",
                "type": "string",
                "enum": [
                  "",
                  "01",
                  "ZZ",
                  null
                ],
                "nullable": true
              },
              "fiscal_responsibilities": {
                "description": "DIAN responsabilidades fiscales (lista 53). Omitted means 'R-99-PN' (no responsable)",
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "O-13",
                    "O-15",
                    "O-23",
                    "O-47",
                    "R-99-PN"
                  ]
                },
                "nullable": true
              },
              "dv": {
                "description": "NIT verification digit",
                "type": "string",
                "nullable": true,
                "pattern": "^[0-9]?$"
              },
              "municipality_code": {
                "description": "DANE municipality code, only for clients domiciled in Colombia",
                "type": "string",
                "nullable": true,
                "pattern": "^([0-9]{5})?$"
              }
            },
            "nullable": true
          },
          "currency": {
            "description": "Currency code (optional at creation, required for stamping)",
            "example": "MXN",
            "type": "string"
          },
          "exchange_rate": {
            "description": "Exchange rate (auto-fetched if not provided at stamp time)",
            "example": 1,
            "type": "number"
          },
          "use": {
            "description": "CFDI use code (optional at creation, required for stamping)",
            "example": "G03",
            "type": "string"
          },
          "payment_form": {
            "description": "Payment form code (optional at creation, required for stamping)",
            "example": "03",
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              "05",
              "06",
              "08",
              "12",
              "13",
              "14",
              "15",
              "17",
              "23",
              "24",
              "25",
              "26",
              "27",
              "28",
              "29",
              "30",
              "31",
              "99"
            ]
          },
          "payment_method": {
            "description": "Payment method (optional at creation, required for stamping)",
            "example": "PUE",
            "type": "string",
            "enum": [
              "PPD",
              "PUE"
            ]
          },
          "items": {
            "description": "Invoice line items (optional at creation, required for stamping)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSchema"
            }
          },
          "series": {
            "description": "Invoice series",
            "example": "A",
            "type": "string"
          },
          "folio_number": {
            "description": "Custom folio number (auto-assigned if not provided at stamp time)",
            "type": "number"
          },
          "exports": {
            "description": "Export classification",
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              null
            ],
            "nullable": true
          },
          "complements": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "type",
                "data"
              ],
              "properties": {
                "type": {
                  "type": "string"
                },
                "data": {
                  "type": "string"
                }
              }
            },
            "nullable": true
          },
          "related_documents": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "relationship",
                "documents"
              ],
              "properties": {
                "relationship": {
                  "type": "string"
                },
                "documents": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            },
            "nullable": true
          },
          "invoice_pdf_notes": {
            "description": "Custom notes to include in the PDF",
            "type": "string"
          },
          "addenda": {
            "description": "XML addenda to include",
            "type": "string",
            "nullable": true
          },
          "global": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "periodicity",
              "months",
              "year"
            ],
            "properties": {
              "periodicity": {
                "type": "string"
              },
              "months": {
                "type": "string"
              },
              "year": {
                "type": "integer"
              }
            },
            "nullable": true
          },
          "automation_type": {
            "description": "Automation to trigger after stamping",
            "type": "string",
            "enum": [
              "payment",
              "none"
            ]
          },
          "send_email": {
            "description": "Whether to send the document via email to the client. Defaults to `true`.",
            "type": "boolean"
          },
          "ignore_emails": {
            "description": "Suppress all notification emails for this document. Takes precedence over\n`send_email` — when `true`, no mail is sent even if `send_email` is `true`.\n",
            "example": false,
            "type": "boolean",
            "nullable": true
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "metadata": {
            "description": "Custom key-value metadata",
            "type": "object",
            "additionalProperties": true,
            "properties": {}
          }
        }
      },
      "DraftInvoiceUpdateInput": {
        "description": "Same accepted fields as `DraftInvoiceInput`, all optional in validation. This does not\nimply PATCH semantics: omitted items become an empty array and other omitted fields\nreceive mapper defaults. Send the complete intended body and read it back before\nstamping. Unknown top-level keys are still rejected\n(`400 validation_failed` / `unexpected_key`).\n",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "invoice_type": {
            "type": "string",
            "enum": [
              "I",
              "E"
            ]
          },
          "client": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "id": {
                "type": "string",
                "nullable": true
              },
              "search": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "on_key",
                  "on_value"
                ],
                "properties": {
                  "on_key": {
                    "type": "string"
                  },
                  "on_value": {
                    "type": "string"
                  },
                  "auto_create": {
                    "type": "boolean",
                    "nullable": true
                  },
                  "safety_check": {
                    "type": "boolean",
                    "nullable": true
                  },
                  "update": {
                    "type": "boolean",
                    "nullable": true
                  }
                },
                "nullable": true
              },
              "address": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "country": {
                    "example": "MEX",
                    "type": "string",
                    "nullable": true,
                    "maxLength": 3
                  },
                  "street": {
                    "example": "Av. Insurgentes Sur",
                    "type": "string",
                    "nullable": true
                  },
                  "zip": {
                    "example": "03100",
                    "type": "string",
                    "nullable": true
                  },
                  "city": {
                    "example": "Ciudad de México",
                    "type": "string",
                    "nullable": true
                  },
                  "state": {
                    "example": "CDMX",
                    "type": "string",
                    "nullable": true
                  },
                  "exterior": {
                    "example": "123",
                    "type": "string",
                    "nullable": true
                  },
                  "interior": {
                    "example": "4B",
                    "type": "string",
                    "nullable": true
                  },
                  "municipality": {
                    "example": "Benito Juárez",
                    "type": "string",
                    "nullable": true
                  },
                  "neighborhood": {
                    "example": "Del Valle",
                    "type": "string",
                    "nullable": true
                  }
                },
                "nullable": true
              },
              "name": {
                "type": "string",
                "nullable": true
              },
              "company": {
                "type": "string",
                "nullable": true
              },
              "phone": {
                "type": "string",
                "nullable": true
              },
              "email": {
                "type": "string",
                "nullable": true
              },
              "bcc": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "metadata": {
                "type": "object",
                "additionalProperties": true,
                "properties": {}
              },
              "legal_name": {
                "type": "string",
                "nullable": true
              },
              "tax_id": {
                "type": "string",
                "nullable": true
              },
              "use": {
                "type": "string",
                "nullable": true
              },
              "tax_system": {
                "type": "string",
                "nullable": true
              },
              "document_type": {
                "description": "DIAN identification document code",
                "type": "string",
                "enum": [
                  "",
                  "11",
                  "12",
                  "13",
                  "21",
                  "22",
                  "31",
                  "41",
                  "42",
                  "47",
                  "48",
                  "50",
                  "91",
                  null
                ],
                "nullable": true
              },
              "organization_type": {
                "description": "1 = persona jurídica, 2 = persona natural",
                "oneOf": [
                  {
                    "type": "string",
                    "enum": [
                      "",
                      "1",
                      "2",
                      null
                    ],
                    "nullable": true
                  },
                  {
                    "type": "number",
                    "enum": [
                      1,
                      2
                    ]
                  }
                ]
              },
              "tribute_code": {
                "description": "'01' = responsable de IVA, 'ZZ' = no aplica",
                "type": "string",
                "enum": [
                  "",
                  "01",
                  "ZZ",
                  null
                ],
                "nullable": true
              },
              "fiscal_responsibilities": {
                "description": "DIAN responsabilidades fiscales (lista 53). Omitted means 'R-99-PN' (no responsable)",
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "O-13",
                    "O-15",
                    "O-23",
                    "O-47",
                    "R-99-PN"
                  ]
                },
                "nullable": true
              },
              "dv": {
                "description": "NIT verification digit",
                "type": "string",
                "nullable": true,
                "pattern": "^[0-9]?$"
              },
              "municipality_code": {
                "description": "DANE municipality code, only for clients domiciled in Colombia",
                "type": "string",
                "nullable": true,
                "pattern": "^([0-9]{5})?$"
              }
            },
            "nullable": true
          },
          "currency": {
            "type": "string"
          },
          "exchange_rate": {
            "type": "number"
          },
          "use": {
            "type": "string"
          },
          "payment_form": {
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              "05",
              "06",
              "08",
              "12",
              "13",
              "14",
              "15",
              "17",
              "23",
              "24",
              "25",
              "26",
              "27",
              "28",
              "29",
              "30",
              "31",
              "99"
            ]
          },
          "payment_method": {
            "type": "string",
            "enum": [
              "PPD",
              "PUE"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSchema"
            }
          },
          "series": {
            "type": "string"
          },
          "folio_number": {
            "type": "number"
          },
          "exports": {
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              null
            ],
            "nullable": true
          },
          "complements": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "type",
                "data"
              ],
              "properties": {
                "type": {
                  "type": "string"
                },
                "data": {
                  "type": "string"
                }
              }
            },
            "nullable": true
          },
          "related_documents": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "relationship",
                "documents"
              ],
              "properties": {
                "relationship": {
                  "type": "string"
                },
                "documents": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            },
            "nullable": true
          },
          "invoice_pdf_notes": {
            "type": "string"
          },
          "addenda": {
            "type": "string",
            "nullable": true
          },
          "global": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "periodicity",
              "months",
              "year"
            ],
            "properties": {
              "periodicity": {
                "type": "string"
              },
              "months": {
                "type": "string"
              },
              "year": {
                "type": "integer"
              }
            },
            "nullable": true
          },
          "automation_type": {
            "type": "string",
            "enum": [
              "payment",
              "none"
            ]
          },
          "send_email": {
            "description": "Whether to send the document via email to the client. Defaults to `true`.",
            "type": "boolean"
          },
          "ignore_emails": {
            "description": "Suppress all notification emails for this document. Takes precedence over\n`send_email` — when `true`, no mail is sent even if `send_email` is `true`.\n",
            "example": false,
            "type": "boolean",
            "nullable": true
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "properties": {}
          }
        }
      },
      "DraftInvoiceOutput": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Draft document ID",
            "example": "abc123def456"
          },
          "draft": {
            "type": "boolean",
            "example": true,
            "description": "Always `true` for draft documents"
          },
          "invoice_type": {
            "type": "string",
            "enum": [
              "I",
              "E"
            ],
            "example": "I"
          },
          "client": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiPublicClient"
              },
              {
                "type": "object",
                "nullable": true,
                "enum": [
                  null
                ]
              }
            ]
          },
          "created_at": {
            "type": "number",
            "format": "int64",
            "description": "Unix timestamp in milliseconds",
            "example": 1677651234000
          },
          "updated_at": {
            "type": "number",
            "format": "int64",
            "description": "Unix timestamp in milliseconds of last update",
            "example": 1677651234000
          },
          "currency": {
            "type": "string",
            "example": "MXN"
          },
          "exchange_rate": {
            "type": "number",
            "example": 1
          },
          "total": {
            "type": "number",
            "example": 5800
          },
          "subtotal": {
            "type": "number",
            "example": 5000
          },
          "discount": {
            "type": "number",
            "example": 0
          },
          "series": {
            "type": "string",
            "example": "A"
          },
          "folio_number": {
            "type": "integer",
            "nullable": true
          },
          "use": {
            "type": "string",
            "example": "G03"
          },
          "payment_form": {
            "type": "string",
            "example": "03"
          },
          "payment_method": {
            "type": "string",
            "example": "PUE"
          },
          "date": {
            "type": "number",
            "nullable": true,
            "description": "Invoice date in milliseconds"
          },
          "livemode": {
            "type": "boolean"
          },
          "owner": {
            "type": "string"
          },
          "from": {
            "type": "string",
            "example": "api",
            "description": "Source of draft creation. Documents created through the public API are stored with `api`; requests carrying the `X-Gigstack-Client: mcp` header (the gigstack MCP server) are stored with `mcp` and behave identically."
          },
          "status": {
            "type": "string",
            "example": "draft",
            "description": "Always `draft` for draft documents"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSchema"
            }
          },
          "addenda": {
            "type": "string"
          },
          "exports": {
            "type": "string"
          },
          "invoice_pdf_notes": {
            "type": "string"
          },
          "global": {
            "type": "object",
            "nullable": true
          },
          "related_documents": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "complements": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "InvoiceIncomeInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`) — body\nvalidation runs in strict allowlist mode, so a field the schema does not declare\nproduces that error. In particular there is no `client_id` field: reference an\nexisting client with `client: { \"id\": \"client_…\" }`, or look one up with\n`client: { \"search\": { \"on_key\": \"tax_id\", \"on_value\": \"…\" } }`. Supplying both `id`\nand `search` on the same object is a `400`.\n\n`team`, `livemode` and `owner` are reserved and injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "client",
          "currency",
          "use",
          "items",
          "payment_form",
          "payment_method"
        ],
        "properties": {
          "date": {
            "type": "number"
          },
          "client": {
            "$ref": "#/components/schemas/EmbeddedClientInput"
          },
          "return_files": {
            "description": "Return base64 encoded PDF and XML files in response",
            "example": true,
            "type": "boolean"
          },
          "currency": {
            "example": "MXN",
            "type": "string"
          },
          "exchange_rate": {
            "description": "Exchange rate for currency conversion. If not provided, the latest rate from our rates collection will be used automatically.",
            "example": 1,
            "type": "number"
          },
          "folio_number": {
            "example": 123,
            "type": "number"
          },
          "series": {
            "example": "A",
            "type": "string"
          },
          "idempotency_key": {
            "description": "Your identifier for this invoice, for example your order id. With it, sending the same request\nagain cannot issue a second CFDI or charge a second credit:\n\n- Once the invoice exists, the same key answers `400` with `duplicate: true` and the existing `uuid`.\n- While another request with the key is being processed, it answers `409` `idempotency_in_progress`.\n- After a `503` `PAC_OUTCOME_UNKNOWN`, a retry with the key resends the exact same XML and folio, so\n  the PAC either stamps it once or reports the stamp it already made.\n- A definitive rejection (for example the SAT refusing the data) frees the key, so you can fix the\n  body and send it again under the same key.\n\nScoped to your team and the credential's mode. Required on every item of `POST /invoices/income/batch`.\n",
            "example": "unique_key_123",
            "type": "string",
            "nullable": true
          },
          "use": {
            "example": "G03",
            "type": "string"
          },
          "exports": {
            "example": "01",
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              null
            ],
            "nullable": true
          },
          "complements": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "type",
                "data"
              ],
              "properties": {
                "type": {
                  "example": "custom",
                  "type": "string"
                },
                "data": {
                  "example": "<xml>...</xml>",
                  "type": "string"
                }
              }
            },
            "nullable": true
          },
          "related_documents": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "relationship",
                "documents"
              ],
              "properties": {
                "relationship": {
                  "example": "04",
                  "type": "string"
                },
                "documents": {
                  "type": "array",
                  "items": {
                    "example": "12345678-1234-1234-1234-123456789012",
                    "type": "string"
                  }
                }
              }
            },
            "nullable": true
          },
          "invoice_pdf_notes": {
            "example": "Additional notes for PDF",
            "type": "string"
          },
          "addenda": {
            "example": "<addenda>...</addenda>",
            "type": "string",
            "nullable": true
          },
          "send_email": {
            "description": "Whether to send the document via email to the client. Defaults to `true`.",
            "example": true,
            "type": "boolean"
          },
          "ignore_emails": {
            "description": "Suppress all notification emails for this document. Takes precedence over\n`send_email` — when `true`, no mail is sent even if `send_email` is `true`.\n",
            "example": false,
            "type": "boolean",
            "nullable": true
          },
          "emails": {
            "example": [
              "client@example.com"
            ],
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "properties": {}
          },
          "automation_type": {
            "description": "Optional. Invoice automation type:\n- `payment`: Create invoice with payment automation\n- `none`: No automation, create invoice only\n",
            "example": "payment",
            "type": "string",
            "enum": [
              "payment",
              "none"
            ]
          },
          "global": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "periodicity",
              "months",
              "year"
            ],
            "properties": {
              "periodicity": {
                "example": "04",
                "type": "string"
              },
              "months": {
                "example": "01",
                "type": "string"
              },
              "year": {
                "example": 2024,
                "type": "integer"
              }
            },
            "nullable": true
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSchema"
            }
          },
          "payment_form": {
            "example": "03",
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              "05",
              "06",
              "08",
              "12",
              "13",
              "14",
              "15",
              "17",
              "23",
              "24",
              "25",
              "26",
              "27",
              "28",
              "29",
              "30",
              "31",
              "99"
            ]
          },
          "payment_method": {
            "example": "PUE",
            "type": "string",
            "enum": [
              "PPD",
              "PUE"
            ]
          }
        }
      },
      "InvoiceEgressInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`) — body\nvalidation runs in strict allowlist mode, so a field the schema does not declare\nproduces that error. In particular there is no `client_id` field: reference an\nexisting client with `client: { \"id\": \"client_…\" }`, or look one up with\n`client: { \"search\": { \"on_key\": \"tax_id\", \"on_value\": \"…\" } }`. Supplying both `id`\nand `search` on the same object is a `400`.\n\n`team`, `livemode` and `owner` are reserved and injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "client",
          "currency",
          "use",
          "items",
          "payment_form"
        ],
        "properties": {
          "date": {
            "description": "Unix timestamp for invoice date",
            "example": 1640995200,
            "type": "number"
          },
          "client": {
            "$ref": "#/components/schemas/EmbeddedClientInput"
          },
          "return_files": {
            "description": "Return base64 encoded PDF and XML files in response",
            "example": true,
            "type": "boolean"
          },
          "currency": {
            "example": "MXN",
            "type": "string"
          },
          "exchange_rate": {
            "description": "Exchange rate for currency conversion. If not provided, the latest rate from our rates collection will be used automatically.",
            "example": 1,
            "type": "number"
          },
          "folio_number": {
            "example": 123,
            "type": "number"
          },
          "series": {
            "description": "Optional. Defaults to the team's credit-note serie, then 'E'.",
            "example": "A",
            "type": "string"
          },
          "idempotency_key": {
            "description": "Optional idempotency key to prevent duplicate invoices",
            "example": "unique_key_123",
            "type": "string",
            "nullable": true
          },
          "use": {
            "example": "G03",
            "type": "string"
          },
          "exports": {
            "example": "01",
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              null
            ],
            "nullable": true
          },
          "complements": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "type",
                "data"
              ],
              "properties": {
                "type": {
                  "example": "custom",
                  "type": "string"
                },
                "data": {
                  "example": "<xml>...</xml>",
                  "type": "string"
                }
              }
            },
            "nullable": true
          },
          "related_documents": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "relationship",
                "documents"
              ],
              "properties": {
                "relationship": {
                  "example": "04",
                  "type": "string"
                },
                "documents": {
                  "type": "array",
                  "items": {
                    "example": "12345678-1234-1234-1234-123456789012",
                    "type": "string"
                  }
                }
              }
            },
            "nullable": true
          },
          "invoice_pdf_notes": {
            "example": "Additional notes for PDF",
            "type": "string"
          },
          "addenda": {
            "example": "<addenda>...</addenda>",
            "type": "string",
            "nullable": true
          },
          "send_email": {
            "description": "Whether to send the document via email to the client. Defaults to `true`.",
            "example": true,
            "type": "boolean"
          },
          "ignore_emails": {
            "description": "Suppress all notification emails for this document. Takes precedence over\n`send_email` — when `true`, no mail is sent even if `send_email` is `true`.\n",
            "example": false,
            "type": "boolean",
            "nullable": true
          },
          "emails": {
            "example": [
              "client@example.com"
            ],
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "properties": {}
          },
          "automation_type": {
            "description": "Payment automation type:\n- `none`: No automation, create invoice only\n",
            "example": "none",
            "type": "string",
            "enum": [
              "none"
            ]
          },
          "items": {
            "description": "Line items. Only `quantity` is required on each item; everything else is optional or resolved from the referenced service.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSchema"
            }
          },
          "payment_form": {
            "example": "03",
            "type": "string"
          },
          "payment_method": {
            "description": "CFDI `MetodoPago`. Optional — defaults to `PUE` when omitted, which is how every\negress invoice was stamped before this field existed.\n\nWith `PPD`, SAT requires `payment_form` to be `99` (\"Por definir\"); any other\nvalue you send is overridden to `99` rather than rejected.\n",
            "example": "PUE",
            "default": "PUE",
            "type": "string",
            "enum": [
              "PPD",
              "PUE"
            ]
          }
        }
      },
      "PaymentComplementRelatedDocument": {
        "type": "object",
        "required": [
          "uuid",
          "amount",
          "installment",
          "last_balance",
          "currency"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "description": "UUID (folio fiscal) of the PPD invoice being paid.",
            "example": "A1B2C3D4-E5F6-7890-ABCD-1234567890AB"
          },
          "amount": {
            "type": "number",
            "description": "Amount paid against this invoice in this payment (ImpPagado).",
            "example": 116
          },
          "installment": {
            "type": "integer",
            "description": "Payment number for this invoice (NumParcialidad), starting at 1.",
            "example": 1
          },
          "last_balance": {
            "type": "number",
            "description": "Outstanding balance before this payment (ImpSaldoAnt).",
            "example": 116
          },
          "currency": {
            "type": "string",
            "description": "Currency of the related invoice (MonedaDR).",
            "example": "MXN"
          },
          "exchange": {
            "type": "number",
            "description": "Exchange rate to the payment currency (EquivalenciaDR). Defaults to 1 when currencies match.",
            "example": 1
          },
          "series": {
            "type": "string",
            "nullable": true,
            "description": "Series of the related invoice (optional)."
          },
          "folio_number": {
            "type": "string",
            "nullable": true,
            "description": "Folio of the related invoice (optional)."
          },
          "taxes": {
            "type": "array",
            "description": "Taxes carried by this related document, mirrored onto the payment (ImpuestosDR).",
            "items": {
              "type": "object",
              "required": [
                "base",
                "rate",
                "factor",
                "type"
              ],
              "properties": {
                "base": {
                  "type": "number",
                  "example": 100
                },
                "rate": {
                  "type": "string",
                  "description": "Tax rate as a string, e.g. '0.16'.",
                  "example": "0.16"
                },
                "factor": {
                  "type": "string",
                  "enum": [
                    "Tasa",
                    "Cuota",
                    "Exento"
                  ],
                  "example": "Tasa"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "IVA",
                    "ISR",
                    "IEPS"
                  ],
                  "example": "IVA"
                },
                "key": {
                  "type": "string",
                  "nullable": true
                },
                "withholding": {
                  "type": "boolean",
                  "example": false
                },
                "inclusive": {
                  "type": "boolean",
                  "example": false
                }
              }
            }
          }
        }
      },
      "PaymentComplementPayment": {
        "type": "object",
        "required": [
          "payment_form",
          "date",
          "currency",
          "related_documents"
        ],
        "properties": {
          "payment_form": {
            "type": "string",
            "description": "SAT c_FormaPago code (FormaDePagoP), e.g. '03' for transfer.",
            "example": "03"
          },
          "date": {
            "type": "string",
            "description": "Payment date/time (FechaPago), ISO 8601.",
            "example": "2026-07-24T12:00:00"
          },
          "currency": {
            "type": "string",
            "description": "Payment currency (MonedaP).",
            "example": "MXN"
          },
          "exchange": {
            "type": "number",
            "description": "Payment exchange rate to MXN (TipoCambioP). Defaults to 1.",
            "example": 1
          },
          "numOperacion": {
            "type": "string",
            "nullable": true
          },
          "rfcEmisorCtaOrd": {
            "type": "string",
            "nullable": true
          },
          "nomBancoOrdExt": {
            "type": "string",
            "nullable": true
          },
          "ctaOrdenante": {
            "type": "string",
            "nullable": true
          },
          "rfcEmisorCtaBen": {
            "type": "string",
            "nullable": true
          },
          "ctaBeneficiario": {
            "type": "string",
            "nullable": true
          },
          "related_documents": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/PaymentComplementRelatedDocument"
            }
          }
        }
      },
      "PaymentComplementInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "client",
          "complements"
        ],
        "properties": {
          "date": {
            "description": "Comprobante date in epoch milliseconds. Defaults to now.",
            "example": 1784915988000,
            "type": "number"
          },
          "client": {
            "$ref": "#/components/schemas/EmbeddedClientInput"
          },
          "return_files": {
            "description": "When true, includes base64 XML + PDF in the response.",
            "type": "boolean"
          },
          "currency": {
            "type": "string"
          },
          "exchange_rate": {
            "type": "number"
          },
          "folio_number": {
            "description": "Optional custom folio. When set, stamps with that exact folio.",
            "type": "number"
          },
          "series": {
            "description": "Override the series. Defaults to the team's payments series (invoice_serie_payments).",
            "type": "string"
          },
          "idempotency_key": {
            "type": "string",
            "nullable": true
          },
          "use": {
            "type": "string"
          },
          "exports": {
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              null
            ],
            "nullable": true
          },
          "complements": {
            "description": "Payment complement groups. Normally a single entry with type 'payment'.",
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "data"
              ],
              "properties": {
                "type": {
                  "description": "Complement type. Defaults to 'pago' (required so the parent PPD balance updates).",
                  "example": "pago",
                  "type": "string"
                },
                "data": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "payment_form",
                      "date",
                      "currency",
                      "related_documents"
                    ],
                    "properties": {
                      "payment_form": {
                        "description": "SAT c_FormaPago code (FormaDePagoP), e.g. '03' for transfer.",
                        "example": "03",
                        "type": "string"
                      },
                      "date": {
                        "description": "Payment date/time (FechaPago), ISO 8601.",
                        "example": "2026-07-24T12:00:00.000Z",
                        "type": "string"
                      },
                      "currency": {
                        "description": "Payment currency (MonedaP).",
                        "example": "MXN",
                        "type": "string"
                      },
                      "exchange": {
                        "description": "Payment exchange rate to MXN (TipoCambioP). Defaults to 1.",
                        "example": 1,
                        "type": "number"
                      },
                      "numOperacion": {
                        "type": "string",
                        "nullable": true
                      },
                      "rfcEmisorCtaOrd": {
                        "type": "string",
                        "nullable": true
                      },
                      "nomBancoOrdExt": {
                        "type": "string",
                        "nullable": true
                      },
                      "ctaOrdenante": {
                        "type": "string",
                        "nullable": true
                      },
                      "rfcEmisorCtaBen": {
                        "type": "string",
                        "nullable": true
                      },
                      "ctaBeneficiario": {
                        "type": "string",
                        "nullable": true
                      },
                      "related_documents": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "additionalProperties": false,
                          "required": [
                            "uuid",
                            "amount",
                            "installment",
                            "last_balance",
                            "currency"
                          ],
                          "properties": {
                            "uuid": {
                              "description": "UUID (folio fiscal) of the PPD invoice being paid.",
                              "example": "A1B2C3D4-E5F6-7890-ABCD-1234567890AB",
                              "type": "string"
                            },
                            "amount": {
                              "description": "Amount paid against this invoice in this payment (ImpPagado).",
                              "example": 116,
                              "type": "number"
                            },
                            "installment": {
                              "description": "Payment number for this invoice (NumParcialidad), starting at 1.",
                              "example": 1,
                              "type": "number"
                            },
                            "last_balance": {
                              "description": "Outstanding balance before this payment (ImpSaldoAnt).",
                              "example": 116,
                              "type": "number"
                            },
                            "currency": {
                              "description": "Currency of the related invoice (MonedaDR).",
                              "example": "MXN",
                              "type": "string"
                            },
                            "exchange": {
                              "description": "Exchange rate to the payment currency (EquivalenciaDR). Defaults to 1 when currencies match.",
                              "example": 1,
                              "type": "number"
                            },
                            "series": {
                              "description": "Series of the related invoice (optional).",
                              "type": "string",
                              "nullable": true
                            },
                            "folio_number": {
                              "description": "Folio of the related invoice (optional).",
                              "type": "string",
                              "nullable": true
                            },
                            "taxes": {
                              "description": "Taxes carried by this related document, mirrored onto the payment (ImpuestosDR).",
                              "type": "array",
                              "items": {
                                "type": "object",
                                "additionalProperties": false,
                                "required": [
                                  "base",
                                  "rate",
                                  "factor",
                                  "type"
                                ],
                                "properties": {
                                  "base": {
                                    "example": 100,
                                    "type": "number"
                                  },
                                  "rate": {
                                    "description": "Tax rate as a string, e.g. '0.16'.",
                                    "example": "0.16",
                                    "type": "string"
                                  },
                                  "factor": {
                                    "example": "Tasa",
                                    "type": "string"
                                  },
                                  "type": {
                                    "example": "IVA",
                                    "type": "string"
                                  },
                                  "key": {
                                    "type": "string",
                                    "nullable": true
                                  },
                                  "withholding": {
                                    "example": false,
                                    "type": "boolean"
                                  },
                                  "inclusive": {
                                    "example": false,
                                    "type": "boolean"
                                  }
                                }
                              },
                              "nullable": true
                            }
                          }
                        },
                        "minItems": 1
                      }
                    }
                  },
                  "minItems": 1
                }
              }
            },
            "minItems": 1
          },
          "related_documents": {
            "description": "Optional CFDI relations (CfdiRelacionados) at the comprobante level.",
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "relationship",
                "documents"
              ],
              "properties": {
                "relationship": {
                  "description": "SAT c_TipoRelacion code.",
                  "type": "string"
                },
                "documents": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            },
            "nullable": true
          },
          "invoice_pdf_notes": {
            "type": "string"
          },
          "addenda": {
            "type": "string",
            "nullable": true
          },
          "send_email": {
            "type": "boolean"
          },
          "ignore_emails": {
            "type": "boolean",
            "nullable": true
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "properties": {}
          }
        }
      },
      "PaymentItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiPublicService"
          },
          {
            "type": "object",
            "properties": {
              "third_party": {
                "$ref": "#/components/schemas/ApiPublicThirdParty"
              },
              "search": {
                "$ref": "#/components/schemas/ApiPublicSearch"
              }
            }
          }
        ]
      },
      "PaymentAllowedMethod": {
        "type": "object",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "card",
            "description": "Payment method identifier"
          }
        }
      },
      "ApiPublicPaymentProcessorDetails": {
        "type": "object",
        "additionalProperties": {
          "type": "object",
          "properties": {
            "payment_intent": {
              "type": "string",
              "example": "pi_1234567890",
              "description": "Payment processor intent ID"
            },
            "charge": {
              "type": "string",
              "example": "ch_1234567890",
              "description": "Payment processor charge ID"
            },
            "invoice": {
              "type": "string",
              "example": "in_1234567890",
              "description": "Payment processor invoice ID"
            }
          }
        },
        "example": {
          "stripe": {
            "payment_intent": "pi_1234567890",
            "charge": "ch_1234567890",
            "invoice": "in_1234567890"
          }
        }
      },
      "ApiPublicPayment": {
        "type": "object",
        "required": [
          "id",
          "client",
          "currency",
          "exchange_rate",
          "items",
          "team",
          "idempotency_key",
          "from",
          "invoices",
          "livemode",
          "owner",
          "payment_form",
          "payments",
          "receipts",
          "refunds",
          "short_url",
          "status",
          "total",
          "total_refunded",
          "subtotal",
          "taxes",
          "discount",
          "withholding_taxes",
          "created_at",
          "succeeded_at",
          "payment_processor"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "payment_1234567890",
            "description": "Unique payment identifier"
          },
          "client": {
            "$ref": "#/components/schemas/ApiPublicClient"
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            },
            "nullable": true,
            "example": [
              "client@example.com"
            ],
            "description": "Email addresses to notify"
          },
          "currency": {
            "type": "string",
            "example": "MXN",
            "description": "Payment currency"
          },
          "allowed_payment_methods": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentAllowedMethod"
            },
            "nullable": true,
            "description": "Allowed payment methods"
          },
          "exchange_rate": {
            "type": "number",
            "example": 1,
            "description": "Exchange rate used for currency conversion"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentItem"
            },
            "description": "Items included in this payment"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "order_id": "12345"
            },
            "description": "Additional metadata for the payment"
          },
          "invoice_config": {
            "$ref": "#/components/schemas/ApiPublicInvoiceConfig"
          },
          "team": {
            "type": "string",
            "example": "team_1234567890",
            "description": "Team ID this payment belongs to"
          },
          "idempotency_key": {
            "type": "string",
            "example": "unique_key_123",
            "description": "Idempotency key to prevent duplicate payments"
          },
          "from": {
            "type": "string",
            "example": "api",
            "description": "Source of payment creation. Documents created through the public API are stored with `api`; requests carrying the `X-Gigstack-Client: mcp` header (the gigstack MCP server) are stored with `mcp` and behave identically."
          },
          "invoices": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
            ],
            "description": "Associated invoice ids. Invoices stamped by the API are stored under their SAT UUID (folio fiscal)."
          },
          "livemode": {
            "type": "boolean",
            "example": true,
            "description": "Whether this payment is in live mode"
          },
          "owner": {
            "type": "string",
            "example": "user_1234567890",
            "description": "User ID who owns this payment"
          },
          "payment_form": {
            "type": "string",
            "example": "03",
            "description": "SAT payment form code"
          },
          "payments": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [],
            "description": "Related payment IDs"
          },
          "receipts": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "receipt_1234567890"
            ],
            "description": "Associated receipt IDs"
          },
          "refunds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiPublicRefund"
            },
            "description": "Refunds associated with this payment"
          },
          "short_url": {
            "type": "string",
            "example": "https://gigstack.xyz/Xk3mP9",
            "description": "Short URL for payment page"
          },
          "success_url": {
            "type": "string",
            "nullable": true,
            "example": "https://tienda.com/pedido/1234/gracias",
            "description": "Where the payment page returns the payer after a successful payment. Null when not set."
          },
          "status": {
            "type": "string",
            "enum": [
              "requires_payment_method",
              "succeeded",
              "partially_paid",
              "canceled"
            ],
            "example": "succeeded",
            "description": "Current payment status. `partially_paid` means the payment was topped up for\nless than its full amount via `POST /payments/{id}/paid` with `amount_received`\nset below the total — see that endpoint's `amount_received` field.\n"
          },
          "total": {
            "type": "number",
            "example": 1160,
            "description": "Total payment amount including taxes"
          },
          "total_refunded": {
            "type": "number",
            "example": 0,
            "description": "Cumulative refunds in minor units (cents), unlike total which is in currency units. Divide by 100 when comparing these fields for the documented MXN flow."
          },
          "subtotal": {
            "type": "number",
            "example": 1000,
            "description": "Subtotal before taxes"
          },
          "taxes": {
            "type": "number",
            "example": 160,
            "description": "Total tax amount"
          },
          "discount": {
            "type": "number",
            "example": 0,
            "description": "Discount applied"
          },
          "withholding_taxes": {
            "type": "number",
            "example": 0,
            "description": "Withholding taxes amount"
          },
          "created_at": {
            "type": "number",
            "example": 1677651234,
            "description": "Unix timestamp of payment creation"
          },
          "succeeded_at": {
            "type": "number",
            "nullable": true,
            "example": 1677651234,
            "description": "Unix timestamp when payment succeeded"
          },
          "payment_processor": {
            "type": "string",
            "example": "stripe",
            "description": "Payment processor used"
          },
          "payment_processor_details": {
            "$ref": "#/components/schemas/ApiPublicPaymentProcessorDetails"
          },
          "transfer_data": {
            "type": "object",
            "nullable": true,
            "description": "Split-payment transfer configuration (gigstack Connect marketplaces)."
          },
          "split_reference": {
            "type": "string",
            "nullable": true
          },
          "split_role": {
            "type": "string",
            "nullable": true,
            "enum": [
              "master",
              "connect",
              null
            ]
          },
          "counterpart_payment_id": {
            "type": "string",
            "nullable": true
          },
          "original_transfer_data": {
            "type": "object",
            "nullable": true
          },
          "split_payment_ids": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            }
          },
          "parent_payment_id": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "RequestPaymentInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`).\n`team`, `livemode` and `owner` are reserved: they are injected by the auth middleware\nand any value you send for them is discarded.\n",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "client",
          "currency",
          "items"
        ],
        "properties": {
          "client": {
            "$ref": "#/components/schemas/EmbeddedClientInput"
          },
          "send_email": {
            "description": "Whether to send an email notification to the customer. Defaults to `true`. Overridden by `ignore_emails`.",
            "example": true,
            "type": "boolean",
            "nullable": true
          },
          "ignore_emails": {
            "description": "Suppress all notification emails for this payment. Takes precedence over\n`send_email` — the handler stores `ignore_emails ?? (send_email === false)`.\n",
            "example": false,
            "type": "boolean",
            "nullable": true
          },
          "emails": {
            "description": "List of email addresses to send the payment request to",
            "example": [
              "customer@example.com"
            ],
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "automation_type": {
            "description": "Payment automation type. Optional; defaults to `none`.\n- `pue_invoice`: Create PUE (Pago en Una sola Exhibición) invoice immediately when payment succeeds\n- `ppd_invoice_and_complement`: Create PPD (Pago en Parcialidades o Diferido) invoice immediately, then payment complement when payment succeeds\n- `none`: No automation, register payment only\n",
            "example": "pue_invoice",
            "type": "string",
            "enum": [
              "pue_invoice",
              "ppd_invoice_and_complement",
              "none",
              null
            ],
            "nullable": true
          },
          "currency": {
            "description": "Currency code (ISO 4217)",
            "example": "MXN",
            "type": "string"
          },
          "exchange_rate": {
            "description": "Exchange rate for currency conversion. If not provided, the latest rate from our rates collection will be used automatically.",
            "example": 1,
            "type": "number",
            "nullable": true
          },
          "ppd_invoice_id": {
            "type": "string",
            "nullable": true
          },
          "allowed_payment_methods": {
            "description": "Payment methods available to the customer. Optional; when the field is absent it defaults to `['card']`, which every connected processor accepts. An explicit empty list is kept as sent.\n- `card`: Credit/debit card payments\n- `bank`: Mexican bank transfer (SPEI)\n- `oxxo`: OXXO convenience store payments\n- `stripe-spei`: Stripe customer balance payments\n- `mercadopago-wallet`: Mercado Pago wallet (requires `payment_processor: mercadopago`)\n\nThe handler additionally restricts the list to the methods supported by the\nselected `payment_processor` — see the operation description.\n",
            "example": [
              "card",
              "bank",
              "oxxo"
            ],
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "card",
                "bank",
                "oxxo",
                "stripe-spei",
                "mercadopago-wallet"
              ]
            },
            "nullable": true
          },
          "idempotency_key": {
            "description": "Unique key to prevent duplicate payment requests",
            "example": "payment-request-12345",
            "type": "string",
            "nullable": true
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSchema"
            }
          },
          "metadata": {
            "description": "Additional metadata to store with the payment",
            "type": "object",
            "additionalProperties": true,
            "properties": {},
            "nullable": true
          },
          "invoice_config": {
            "description": "Optional invoice configuration to force specific folio and/or serie for the invoice. If folio is null or not provided, the automatic incrementing folio will be used.",
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "serie": {
                "description": "Invoice serie. Will set/create the series for the team if provided.",
                "example": "A",
                "type": "string",
                "nullable": true
              },
              "folio": {
                "description": "Invoice folio number. If null or not provided, uses automatic incrementing folio. Note: when provided, duplicates may occur.",
                "example": 123,
                "type": "number",
                "nullable": true
              }
            },
            "nullable": true
          },
          "payment_processor": {
            "description": "Processor that will host the checkout. Defaults to `stripe`. Every processor\nother than `stripe` requires `currency: MXN`.\n",
            "example": "stripe",
            "type": "string",
            "enum": [
              "stripe",
              "mercadopago",
              "openpay",
              "pagoralia",
              "conekta",
              null
            ],
            "nullable": true
          },
          "success_url": {
            "description": "Where the hosted payment page returns the payer once the payment succeeds.\nUse it so a checkout does not dead-end on the payment page: point it at your\norder confirmation page.\n\nThe payer is shown the destination host and redirected a few seconds after\nthe payment is confirmed; they can also return immediately with a button.\nFor asynchronous methods (SPEI, OXXO) the redirect happens when the payment\nis confirmed, which may be after the payer has closed the page.\n\nValidated on write — a `400` is returned unless the URL:\n  - uses `https`\n  - carries no credentials (`https://user:pass@host`)\n  - contains no whitespace or control characters\n  - resolves to a fully qualified, publicly reachable host\n    (loopback, private and link-local ranges are rejected)\n  - is at most 2048 characters\n",
            "example": "https://tienda.com/pedido/1234/gracias",
            "type": "string",
            "nullable": true,
            "maxLength": 2048,
            "format": "uri"
          }
        }
      },
      "RegisterPaymentInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`).\n`team`, `livemode` and `owner` are reserved and injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "client",
          "automation_type",
          "currency",
          "items",
          "payment_form"
        ],
        "properties": {
          "client": {
            "$ref": "#/components/schemas/EmbeddedClientInput"
          },
          "automation_type": {
            "description": "Payment automation type:\n- `pue_invoice`: Create PUE (Pago en Una sola Exhibición) invoice immediately when payment succeeds\n- `ppd_invoice_and_complement`: Create PPD (Pago en Parcialidades o Diferido) invoice immediately, then payment complement when payment succeeds\n- `none`: No automation, register payment only\n",
            "example": "pue_invoice",
            "type": "string",
            "enum": [
              "pue_invoice",
              "ppd_invoice_and_complement",
              "none"
            ]
          },
          "currency": {
            "description": "Currency code (ISO 4217)",
            "example": "MXN",
            "type": "string"
          },
          "exchange_rate": {
            "description": "Exchange rate for currency conversion. If not provided, the rate from the payment date (or current date if no date specified) will be fetched automatically from our rates collection.",
            "example": 1,
            "type": "number",
            "nullable": true
          },
          "idempotency_key": {
            "description": "Stable key for one business event. A duplicate returns HTTP 400 with error.code resource_conflict, not the existing payment as a successful response. Reconcile the existing record and retain this key; do not create a new key for a retry.",
            "example": "payment-register-12345",
            "type": "string",
            "nullable": true
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSchema"
            },
            "minItems": 1
          },
          "payment_form": {
            "description": "Mexican SAT payment form code:\n- `01`: Cash\n- `02`: Check\n- `03`: Electronic transfer\n- `04`: Credit card\n- `05`: Electronic money\n- `06`: Digital money\n- `08`: Gift voucher\n- `12`: Credit for unregistered bills\n- `13`: Payment by subrogation\n- `14`: Payment by consignment\n- `15`: Condonation\n- `17`: Compensation\n- `23`: Novation\n- `24`: Confusion\n- `25`: Remission of debt\n- `26`: Prescription or expiration\n- `27`: To creditor's satisfaction\n- `28`: Credit card\n- `29`: Debit card\n- `30`: Service card\n- `31`: Applicable only to the complementary concept of donations\n- `99`: To be defined\n",
            "example": "03",
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              "05",
              "06",
              "08",
              "12",
              "13",
              "14",
              "15",
              "17",
              "23",
              "24",
              "25",
              "26",
              "27",
              "28",
              "29",
              "30",
              "31",
              "99"
            ]
          },
          "metadata": {
            "description": "Additional metadata to store with the payment",
            "type": "object",
            "additionalProperties": true,
            "properties": {},
            "nullable": true
          },
          "invoice_config": {
            "description": "Optional invoice configuration. Every field is optional. Controls the folio/serie the\ngenerated invoice will use, its issue date, the global (EOM) period it belongs to, and\nhow long the self-invoicing window stays open.\n",
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "serie": {
                "description": "Invoice serie. Will set/create the series for the team if provided.",
                "example": "A",
                "type": "string",
                "nullable": true
              },
              "folio": {
                "description": "Invoice folio number. If omitted, the automatic incrementing folio is used. When provided, duplicates may occur.",
                "example": 123,
                "type": "number",
                "nullable": true
              },
              "date": {
                "description": "Invoice issue date as a Unix epoch timestamp in **milliseconds**.",
                "example": 1767225600000,
                "type": "number",
                "nullable": true
              },
              "global": {
                "description": "Period of the global (factura global / EOM) invoice this document belongs to.",
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "year": {
                    "description": "Fiscal year, four digits.",
                    "example": 2026,
                    "type": "number",
                    "nullable": true
                  },
                  "months": {
                    "description": "SAT `c_Meses` code. `01`–`12` for a single month; `13`–`18` for the\nbimonthly periods (`13` = Jan–Feb … `18` = Nov–Dec).\n",
                    "example": "01",
                    "type": "string",
                    "nullable": true
                  },
                  "periodicity": {
                    "description": "SAT `c_Periodicidad` code: `01` daily, `02` weekly, `03` fortnightly,\n`04` monthly, `05` bimonthly.\n",
                    "example": "04",
                    "type": "string",
                    "nullable": true
                  }
                },
                "nullable": true
              },
              "validUntil": {
                "description": "Expiry of the self-invoicing window, Unix epoch **milliseconds**.",
                "example": 1769817600000,
                "type": "number",
                "nullable": true
              }
            },
            "nullable": true
          },
          "date": {
            "description": "Unix epoch timestamp in **milliseconds** (13 digits) for when the payment was received. Must be in the past. Defaults to now.",
            "example": 1767225600000,
            "type": "number",
            "nullable": true
          },
          "send_email": {
            "description": "Accepted for compatibility, but on this endpoint it has **no effect** — only\n`ignore_emails` is persisted onto the payment. Use `ignore_emails` to suppress mail.\n",
            "example": true,
            "type": "boolean",
            "nullable": true
          },
          "ignore_emails": {
            "description": "Suppress email and WhatsApp notifications for this payment and any documents\nit automates (invoices, receipts). Defaults to `false`.\n",
            "example": false,
            "type": "boolean",
            "nullable": true
          },
          "ppd_invoice_id": {
            "description": "UUID of an existing PPD invoice to link this payment to. When provided, a payment complement (complemento de pago) will be automatically generated and linked to the PPD invoice. The referenced invoice must have payment_method='PPD', status='valid' and invoice_type='I' — a payment complement only ever settles an income CFDI, never an egress one.",
            "example": "invoice_ppd_1234567890",
            "type": "string",
            "nullable": true
          },
          "transfer_data": {
            "description": "Configuration for splitting payments between master and connect teams in a marketplace.\nOnly available for master teams with marketplace-enabled billing accounts.\n\n**All-or-nothing:** the object itself is optional, but when it is present\n`master`, `connect`, `master_to` and `connect_to` are **all required**.\nSending `transfer_data` with any of them missing fails validation with\n`400 validation_failed`. `connect_custom_config` stays optional.\n",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "master",
              "connect",
              "master_to",
              "connect_to"
            ],
            "properties": {
              "master": {
                "description": "Required when `transfer_data` is present. Percentage of the payment retained by the master team. Must be between 0 and 100 inclusive.",
                "example": 10,
                "type": "number",
                "minimum": 0,
                "maximum": 100
              },
              "connect": {
                "description": "Required when `transfer_data` is present. Tax ID (RFC) or Team ID of the connect team. If not found, a new team will be created.",
                "example": "ABC123456789",
                "type": "string",
                "minLength": 1
              },
              "master_to": {
                "description": "Determines which client to assign to the master payment:\n- `client`: Use the original client from the request\n- `connect`: Create the connect team as a client for the master payment\n",
                "example": "client",
                "type": "string",
                "enum": [
                  "client",
                  "connect"
                ]
              },
              "connect_to": {
                "description": "Determines which client to assign to the connect payment:\n- `client`: Use the original client from the request\n- `master`: Create the master team as a client for the connect payment\n",
                "example": "client",
                "type": "string",
                "enum": [
                  "client",
                  "master"
                ]
              },
              "connect_custom_config": {
                "description": "Optional configuration to customize items in the connect payment",
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "product_key": {
                    "description": "SAT product key to use for connect payment items",
                    "example": "01010101",
                    "type": "string",
                    "nullable": true
                  },
                  "unit_key": {
                    "description": "SAT unit key to use for connect payment items",
                    "example": "E48",
                    "type": "string",
                    "nullable": true
                  },
                  "taxes": {
                    "description": "Custom tax configuration for connect payment items (uses same schema as regular item taxes)",
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "type",
                        "rate",
                        "withholding"
                      ],
                      "properties": {
                        "type": {
                          "description": "Tax type",
                          "example": "IVA",
                          "type": "string",
                          "enum": [
                            "IVA",
                            "ISR",
                            "IEPS"
                          ]
                        },
                        "rate": {
                          "description": "Tax rate as decimal (0.16 = 16%)",
                          "example": 0.16,
                          "type": "number"
                        },
                        "withholding": {
                          "description": "true = retention (deducted from total), false = regular tax (added to subtotal)",
                          "example": false,
                          "type": "boolean"
                        },
                        "base": {
                          "description": "Optional tax base amount",
                          "type": "number",
                          "nullable": true
                        },
                        "factor": {
                          "description": "Optional tax factor",
                          "example": "Tasa",
                          "type": "string",
                          "nullable": true
                        },
                        "inclusive": {
                          "description": "Whether tax is included in the price",
                          "type": "boolean",
                          "nullable": true
                        }
                      }
                    },
                    "nullable": true
                  },
                  "custom_description": {
                    "description": "Custom description for connect payment items",
                    "example": "Professional consulting services",
                    "type": "string",
                    "nullable": true
                  },
                  "custom_price": {
                    "description": "Fixed amount for connect payment (overrides percentage calculation). When set, connect gets this exact amount and master gets the remainder.",
                    "example": 250,
                    "type": "number",
                    "nullable": true,
                    "minimum": 0
                  }
                },
                "nullable": true
              }
            },
            "nullable": true
          }
        }
      },
      "RefundPaymentInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "reason",
          "amount"
        ],
        "properties": {
          "reason": {
            "description": "Reason for the refund",
            "example": "Customer requested cancellation",
            "type": "string"
          },
          "amount": {
            "description": "Amount to refund, in the payment currency. Validation requires **at least 0.01**.\nThe cumulative refunded total may not exceed the payment amount.\n",
            "example": 1160,
            "type": "number",
            "minimum": 0.01
          },
          "external_processor_refund": {
            "description": "Whether to process refund through external payment processor",
            "example": false,
            "type": "boolean",
            "nullable": true
          }
        }
      },
      "InvoiceConfigInput": {
        "type": "object",
        "nullable": true,
        "additionalProperties": false,
        "description": "Optional invoice configuration. Every field is optional. Controls the folio/serie the\ngenerated invoice will use, its issue date, the global (EOM) period it belongs to, and\nhow long the self-invoicing window stays open.\n",
        "properties": {
          "serie": {
            "type": "string",
            "nullable": true,
            "example": "A",
            "description": "Invoice serie. Will set/create the series for the team if provided."
          },
          "folio": {
            "type": "number",
            "nullable": true,
            "example": 123,
            "description": "Invoice folio number. If omitted, the automatic incrementing folio is used. When provided, duplicates may occur."
          },
          "date": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": 1767225600000,
            "description": "Invoice issue date as a Unix epoch timestamp in **milliseconds**."
          },
          "global": {
            "type": "object",
            "nullable": true,
            "additionalProperties": false,
            "description": "Period of the global (factura global / EOM) invoice this document belongs to.",
            "properties": {
              "year": {
                "type": "number",
                "nullable": true,
                "example": 2026,
                "description": "Fiscal year, four digits."
              },
              "months": {
                "type": "string",
                "nullable": true,
                "example": "01",
                "description": "SAT `c_Meses` code. `01`–`12` for a single month; `13`–`18` for the\nbimonthly periods (`13` = Jan–Feb … `18` = Nov–Dec).\n"
              },
              "periodicity": {
                "type": "string",
                "nullable": true,
                "example": "04",
                "description": "SAT `c_Periodicidad` code: `01` daily, `02` weekly, `03` fortnightly,\n`04` monthly, `05` bimonthly.\n"
              }
            }
          },
          "validUntil": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": 1769817600000,
            "description": "Expiry of the self-invoicing window, Unix epoch **milliseconds**."
          }
        }
      },
      "MarkPaymentAsPaidInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "payment_form"
        ],
        "properties": {
          "date": {
            "description": "When the payment was received, as a Unix epoch timestamp in **milliseconds**\n(13 digits). The handler feeds this value directly to `Luxon.fromMillis()` and\ncompares it to `Luxon.now().toMillis()`, so a seconds-precision value is\ninterpreted as a 1970 date rather than rejected. Defaults to now; a future\nvalue returns `400`.\n",
            "example": 1767225600000,
            "type": "number",
            "nullable": true
          },
          "send_email": {
            "description": "Whether to send email notifications. Overridden by `ignore_emails`.",
            "example": true,
            "type": "boolean",
            "nullable": true
          },
          "ignore_emails": {
            "description": "Suppress notification emails. Takes precedence over `send_email` — the handler\nresolves `ignore_emails ?? (send_email === false)`.\n",
            "example": false,
            "type": "boolean",
            "nullable": true
          },
          "amount_received": {
            "description": "Cumulative amount received so far, in the payment's currency (**not** cents —\nconverted internally to match the payment's stored amount). Omit it, or pass\nthe full payment amount, to mark the payment fully `succeeded` (the default\nbehavior). Pass a value **less than** the payment amount to record a partial\ntop-up instead: the payment is set to `partially_paid` with this cumulative\namount, which must exceed the amount already received. A value **greater than**\nthe payment amount is rejected with `400`.\n\nPartial funding additionally requires the team's\n`automatePartialPaymentComplements` default to be enabled and the payment to\nalready carry a `payment_complement` automation (i.e. it originated from a PPD\ninvoice flow) — otherwise the request is rejected with `400`.\n",
            "example": 500,
            "type": "number",
            "nullable": true,
            "minimum": 0.01
          },
          "payment_form": {
            "description": "SAT payment form code",
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              "05",
              "06",
              "08",
              "12",
              "13",
              "14",
              "15",
              "17",
              "23",
              "24",
              "25",
              "26",
              "27",
              "28",
              "29",
              "30",
              "31",
              "99"
            ]
          }
        }
      },
      "UpdatePaymentInput": {
        "description": "Body for the PUT /payments/{id} endpoint. At least one of `items`, `automation_type` or `client` must be present.\n\n- `items`: Update the `description` of one or more items in the payment, matched by item `id`. Only `description` can be modified — taxes, discounts, quantities and unit prices are immutable from this endpoint and any other field is rejected.\n- `automation_type`: Add automations to a payment that does not have any. If the payment already has automations, the request is rejected with 400. When non-empty automations are added and the payment status is `succeeded`, the status is flipped to `succeeded_` after the update so the automation trigger can re-fire.\n- `client`: Update fields of the client embedded in the payment (name, email, fiscal info, address, etc.). The client `id` cannot be changed. Any provided field is also written to the matching `/clients/{id}` document via a partial merge, so the client master record stays in sync with the payment. Fiscal/SAT validation is **not** re-run from this endpoint — use `PUT /clients/{id}` if you need that.\n",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "items": {
            "description": "List of items to update. Only the `description` of each item can be modified.",
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "description"
              ],
              "properties": {
                "id": {
                  "description": "Item id within the payment",
                  "example": "service_1234567890",
                  "type": "string",
                  "minLength": 1
                },
                "description": {
                  "description": "New description for the item",
                  "example": "Servicio de consultoría profesional - corregido",
                  "type": "string",
                  "minLength": 1
                }
              }
            },
            "nullable": true,
            "minItems": 1
          },
          "automation_type": {
            "description": "Automation to attach to the payment. Only allowed if the payment currently has no automations.",
            "example": "pue_invoice",
            "type": "string",
            "enum": [
              "pue_invoice",
              "ppd_invoice_and_complement",
              "none",
              null
            ],
            "nullable": true
          },
          "invoice_config": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "serie": {
                "type": "string",
                "nullable": true
              },
              "folio": {
                "type": "number",
                "nullable": true
              },
              "date": {
                "type": "number",
                "nullable": true
              },
              "global": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "year": {
                    "type": "number",
                    "nullable": true
                  },
                  "months": {
                    "type": "string",
                    "nullable": true
                  },
                  "periodicity": {
                    "type": "string",
                    "nullable": true
                  }
                },
                "nullable": true
              },
              "validUntil": {
                "type": "number",
                "nullable": true
              }
            },
            "nullable": true
          },
          "client": {
            "description": "Partial update for the client embedded in the payment. Only the listed fields can be modified — the client `id` cannot be changed. Each provided field is propagated to the `/clients/{id}` master document via a partial merge.\n",
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "name": {
                "example": "Juan Pérez García",
                "type": "string",
                "nullable": true
              },
              "company": {
                "example": "Acme S.A. de C.V.",
                "type": "string",
                "nullable": true
              },
              "phone": {
                "example": "+525555555555",
                "type": "string",
                "nullable": true
              },
              "email": {
                "example": "juan.perez@ejemplo.com",
                "type": "string",
                "nullable": true,
                "format": "email"
              },
              "bcc": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "nullable": true
              },
              "metadata": {
                "type": "object",
                "additionalProperties": true,
                "properties": {},
                "nullable": true
              },
              "legal_name": {
                "example": "JUAN PEREZ GARCIA",
                "type": "string",
                "nullable": true
              },
              "tax_id": {
                "description": "Mexican SAT RFC. Mirrored to the legacy `rfc` field on the client document.",
                "example": "PEGJ800101ABC",
                "type": "string",
                "nullable": true
              },
              "use": {
                "example": "G03",
                "type": "string",
                "nullable": true
              },
              "tax_system": {
                "example": "601",
                "type": "string",
                "nullable": true
              },
              "address": {
                "description": "Partial address update. Only fields present in the request are merged onto the existing address; absent fields are kept as-is.",
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "country": {
                    "example": "MEX",
                    "type": "string",
                    "nullable": true,
                    "maxLength": 3
                  },
                  "street": {
                    "type": "string",
                    "nullable": true
                  },
                  "zip": {
                    "type": "string",
                    "nullable": true
                  },
                  "city": {
                    "type": "string",
                    "nullable": true
                  },
                  "state": {
                    "type": "string",
                    "nullable": true
                  },
                  "exterior": {
                    "type": "string",
                    "nullable": true
                  },
                  "interior": {
                    "type": "string",
                    "nullable": true
                  },
                  "municipality": {
                    "type": "string",
                    "nullable": true
                  },
                  "neighborhood": {
                    "type": "string",
                    "nullable": true
                  }
                },
                "nullable": true
              }
            },
            "nullable": true
          }
        }
      },
      "ApiPublicIncomeInvoice": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
            "description": "SAT UUID (folio fiscal)"
          },
          "client": {
            "$ref": "#/components/schemas/ApiPublicClient"
          },
          "created_at": {
            "type": "number",
            "example": 1677651234,
            "description": "Invoice creation timestamp"
          },
          "currency": {
            "type": "string",
            "example": "MXN",
            "description": "Invoice currency"
          },
          "exchange_rate": {
            "type": "number",
            "example": 1,
            "description": "Exchange rate used"
          },
          "total": {
            "type": "number",
            "example": 1160,
            "description": "Total invoice amount"
          },
          "subtotal": {
            "type": "number",
            "example": 1000,
            "description": "Subtotal before taxes"
          },
          "taxes": {
            "type": "number",
            "example": 160,
            "description": "Total tax amount"
          },
          "discount": {
            "type": "number",
            "example": 0,
            "description": "Total discount amount"
          },
          "withholding_taxes": {
            "type": "number",
            "example": 0,
            "description": "Total withholding tax amount"
          },
          "series": {
            "type": "string",
            "example": "A",
            "description": "Invoice series"
          },
          "folio_number": {
            "type": "number",
            "example": 123,
            "description": "Invoice folio number"
          },
          "invoice_type": {
            "type": "string",
            "enum": [
              "I",
              "E",
              "P",
              "N"
            ],
            "example": "I",
            "description": "Invoice type (I=Income, E=Egress, P=Payment, N=Nomina)"
          },
          "use": {
            "type": "string",
            "example": "G03",
            "description": "Mexican SAT usage code"
          },
          "payment_form": {
            "type": "string",
            "example": "03",
            "description": "Mexican SAT payment form code"
          },
          "payment_method": {
            "type": "string",
            "example": "PUE",
            "description": "Payment method (PUE/PPD)"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "pending",
              "valid",
              "canceled",
              "cancelled"
            ],
            "example": "valid",
            "description": "Invoice status as stored. A stamped invoice is `valid`; a cancelled one is\n`canceled`. `cancelled` (double L) appears only on older records — new writes\nalways use `canceled`. `draft` is a pre-factura that has not been stamped.\n"
          },
          "livemode": {
            "type": "boolean",
            "example": true,
            "description": "Whether this is a live invoice"
          },
          "owner": {
            "type": "string",
            "example": "user_1234567890",
            "description": "User who created the invoice"
          },
          "from": {
            "type": "string",
            "example": "api",
            "description": "Source of invoice creation. Documents created through the public API are stored with `api`; requests carrying the `X-Gigstack-Client: mcp` header (the gigstack MCP server) are stored with `mcp` and behave identically."
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "example": "item_1234567890"
                },
                "description": {
                  "type": "string",
                  "example": "Professional consulting services"
                },
                "product_key": {
                  "type": "string",
                  "example": "80141503"
                },
                "quantity": {
                  "type": "number",
                  "example": 1
                },
                "unit_price": {
                  "type": "number",
                  "example": 1000
                },
                "unit_key": {
                  "type": "string",
                  "example": "E48"
                },
                "unit_name": {
                  "type": "string",
                  "example": "Servicio"
                },
                "sku": {
                  "type": "string",
                  "example": "CONS-001"
                },
                "taxability": {
                  "type": "string",
                  "enum": [
                    "01",
                    "02"
                  ],
                  "example": "01"
                },
                "taxes": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TaxSchema"
                  }
                }
              }
            }
          },
          "payments": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "payment_1234567890"
            ],
            "description": "Associated payment IDs"
          },
          "invoices": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [],
            "description": "Related invoice IDs"
          },
          "stamp": {
            "type": "object",
            "nullable": true,
            "properties": {
              "sello": {
                "type": "string",
                "example": "ABC123..."
              },
              "stamp_at": {
                "type": "number",
                "example": 1677651234
              }
            }
          },
          "cancellation": {
            "type": "object",
            "nullable": true,
            "properties": {
              "cancellation_status": {
                "type": "string",
                "example": "cancelled"
              },
              "cancelled_at": {
                "type": "number",
                "example": 1677651234
              },
              "motive": {
                "type": "string",
                "example": "02"
              },
              "code": {
                "type": "string",
                "example": "201"
              }
            }
          },
          "verification_url": {
            "type": "string",
            "example": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx",
            "description": "SAT verification URL"
          },
          "exports": {
            "type": "string",
            "example": "01",
            "description": "Export indicator"
          },
          "addenda": {
            "type": "string",
            "example": "",
            "description": "Additional XML addenda"
          },
          "invoice_pdf_notes": {
            "type": "string",
            "example": "Additional notes for PDF",
            "description": "Custom notes for PDF generation"
          },
          "files": {
            "type": "object",
            "nullable": true,
            "description": "Base64 encoded files (only returned when return_files=true)",
            "properties": {
              "pdf": {
                "type": "string",
                "example": "JVBERi0xLjQKJeLjz9MKMSAwIG9ia...",
                "description": "Base64 encoded PDF file"
              },
              "xml": {
                "type": "string",
                "example": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4...",
                "description": "Base64 encoded XML file"
              }
            }
          },
          "idempotency_key": {
            "type": "string",
            "nullable": true
          },
          "team": {
            "type": "string",
            "example": "team_1234567890"
          },
          "billing_account": {
            "type": "string",
            "nullable": true
          },
          "date": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Comprobante date, epoch ms."
          },
          "payment_conditions": {
            "type": "string",
            "nullable": true
          },
          "global": {
            "type": "object",
            "nullable": true,
            "description": "Global-invoice period (see the Global Invoices guide).",
            "properties": {
              "periodicity": {
                "type": "string"
              },
              "months": {
                "type": "string"
              },
              "year": {
                "type": "integer"
              }
            }
          },
          "related_documents": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object",
              "properties": {
                "relationship": {
                  "type": "string"
                },
                "documents": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "complements": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object"
            }
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "emails": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            }
          },
          "issuer_info": {
            "type": "object",
            "nullable": true,
            "properties": {
              "legal_name": {
                "type": "string"
              },
              "tax_id": {
                "type": "string"
              },
              "tax_system": {
                "type": "string"
              },
              "zip": {
                "type": "string"
              }
            }
          },
          "namespaces": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object",
              "properties": {
                "prefix": {
                  "type": "string"
                },
                "uri": {
                  "type": "string"
                },
                "schema_location": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "ApiPublicTeam": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "team_1234567890"
          },
          "legal_name": {
            "type": "string",
            "nullable": true,
            "example": "Empresa de Tecnología S.A. de C.V.",
            "description": "Official registered legal name of the company/team"
          },
          "address": {
            "type": "object",
            "nullable": true,
            "properties": {
              "country": {
                "type": "string",
                "nullable": true,
                "example": "MEX"
              },
              "street": {
                "type": "string",
                "nullable": true,
                "example": "Av. Insurgentes Sur 456"
              },
              "zip": {
                "type": "string",
                "nullable": true,
                "example": "03100"
              },
              "city": {
                "type": "string",
                "nullable": true,
                "example": "Ciudad de México"
              },
              "state": {
                "type": "string",
                "nullable": true,
                "example": "CDMX"
              },
              "exterior": {
                "type": "string",
                "nullable": true,
                "example": "96"
              },
              "interior": {
                "type": "string",
                "nullable": true,
                "example": "10"
              },
              "neighborhood": {
                "type": "string",
                "nullable": true,
                "example": "Polanco"
              }
            }
          },
          "brand": {
            "type": "object",
            "properties": {
              "alias": {
                "type": "string",
                "nullable": true,
                "example": "Mi Empresa"
              },
              "primary_color": {
                "type": "string",
                "nullable": true,
                "example": "#007bff"
              },
              "secondary_color": {
                "type": "string",
                "nullable": true,
                "example": "#6c757d"
              },
              "logo": {
                "type": "string",
                "nullable": true,
                "example": "https://example.com/logo.png"
              }
            }
          },
          "settings": {
            "type": "object",
            "nullable": true,
            "properties": {
              "avoid_automations_on_currencies": {
                "type": "array",
                "nullable": true,
                "items": {
                  "type": "string"
                },
                "example": [
                  "USD",
                  "EUR"
                ]
              },
              "default_description": {
                "type": "string",
                "nullable": true,
                "example": "Default invoice description"
              },
              "taxes": {
                "type": "array",
                "nullable": true,
                "items": {
                  "type": "object"
                }
              },
              "taxes_usd": {
                "oneOf": [
                  {
                    "type": "array",
                    "nullable": true,
                    "items": {
                      "type": "object"
                    }
                  },
                  {
                    "type": "boolean",
                    "nullable": true
                  }
                ]
              },
              "emails": {
                "type": "object",
                "properties": {
                  "invoices_bcc": {
                    "type": "array",
                    "nullable": true,
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "accounting@example.com"
                    ]
                  },
                  "avoid_invoice_emails": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "avoid_test_invoice_emails": {
                    "type": "boolean",
                    "nullable": true,
                    "example": true
                  },
                  "avoid_receipts_emails": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  }
                }
              },
              "override_item_description": {
                "type": "string",
                "nullable": true,
                "example": "Custom item description"
              },
              "global_invoice_disabled": {
                "type": "boolean",
                "nullable": true,
                "example": false
              },
              "complements": {
                "type": "array",
                "nullable": true,
                "items": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "string",
                      "nullable": true
                    },
                    "description": {
                      "type": "string",
                      "nullable": true
                    },
                    "type": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              },
              "uses_on_self_invoice_portal": {
                "type": "array",
                "nullable": true,
                "items": {
                  "type": "string"
                },
                "example": [
                  "G03",
                  "S01"
                ]
              },
              "invoice_pdf_notes": {
                "type": "string",
                "nullable": true,
                "example": "Additional notes for PDF"
              },
              "product_key": {
                "type": "string",
                "nullable": true,
                "example": "81112209"
              },
              "unit_key": {
                "type": "string",
                "nullable": true,
                "example": "E48"
              },
              "use": {
                "type": "string",
                "nullable": true,
                "example": "G03"
              },
              "automate_complement_for_ppd_invoices": {
                "type": "boolean",
                "nullable": true,
                "example": true
              },
              "withholding_taxes": {
                "type": "array",
                "nullable": true,
                "items": {
                  "type": "object"
                }
              },
              "customer_portal_id": {
                "type": "string",
                "nullable": true,
                "example": "portal_1234567890"
              },
              "periodicity": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "label": {
                    "type": "string",
                    "example": "Mes"
                  },
                  "value": {
                    "type": "string",
                    "example": "month"
                  }
                }
              },
              "default_series": {
                "type": "object",
                "properties": {
                  "income": {
                    "type": "object",
                    "properties": {
                      "serie": {
                        "type": "string",
                        "nullable": true,
                        "example": "A"
                      }
                    }
                  },
                  "complements": {
                    "type": "object",
                    "properties": {
                      "serie": {
                        "type": "string",
                        "nullable": true,
                        "example": "P"
                      }
                    }
                  },
                  "credit_note": {
                    "type": "object",
                    "properties": {
                      "serie": {
                        "type": "string",
                        "nullable": true,
                        "example": "NC"
                      }
                    }
                  }
                }
              }
            }
          },
          "tax_id": {
            "type": "string",
            "nullable": true,
            "example": "EMP800101ABC"
          },
          "tax_system": {
            "type": "string",
            "nullable": true,
            "example": "601"
          },
          "support_email": {
            "type": "string",
            "nullable": true,
            "example": "support@empresa.com"
          },
          "support_phone": {
            "type": "string",
            "nullable": true,
            "example": "+52 55 1234 5678"
          },
          "owner": {
            "type": "string",
            "nullable": true,
            "example": "user_1234567890"
          },
          "created_at": {
            "type": "number",
            "nullable": true,
            "example": 1677651234
          },
          "sat": {
            "type": "object",
            "properties": {
              "completed": {
                "type": "boolean",
                "nullable": true,
                "example": true
              },
              "connected_at": {
                "type": "number",
                "nullable": true,
                "example": 1677651234
              },
              "csd_expires_at": {
                "type": "number",
                "nullable": true,
                "example": 1924991999
              }
            }
          },
          "members": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "nullable": true,
                  "example": "user_1234567890"
                },
                "email": {
                  "type": "string",
                  "nullable": true,
                  "example": "member@empresa.com"
                },
                "role": {
                  "type": "string",
                  "nullable": true,
                  "example": "admin"
                }
              }
            }
          },
          "integrations": {
            "type": "object",
            "properties": {
              "stripe": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "mercadopago": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "clip": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "whmcs": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "paypal": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "openpay": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "conekta": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "bank": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "shopify": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "zapier": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "airtable": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "google_sheets": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "payments"
                  }
                }
              },
              "hilos": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "nullable": true,
                    "example": false
                  },
                  "category": {
                    "type": "string",
                    "nullable": true,
                    "example": "messaging"
                  }
                }
              }
            }
          },
          "credit_limit": {
            "type": "number",
            "nullable": true,
            "example": 1000,
            "description": "Maximum number of documents (credits) the team can create per billing period. Null means no per-team limit (shared billing account pool)."
          },
          "used_credits": {
            "type": "number",
            "example": 250,
            "description": "Number of credits used by this team in the current billing period."
          },
          "credit_period_start": {
            "type": "number",
            "nullable": true,
            "example": 1677651234000,
            "description": "Unix timestamp (milliseconds) when the current credit period started. Resets each billing cycle."
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "example": {
              "custom_field": "value"
            }
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "`pending_deletion` after `DELETE /teams/{id}`; otherwise usually absent or `active`.",
            "example": "active"
          },
          "scheduled_deletion": {
            "type": "object",
            "nullable": true,
            "description": "Set when the team is scheduled for deletion.",
            "properties": {
              "date": {
                "description": "When the team will be deleted."
              },
              "flagged_at": {
                "type": "integer",
                "format": "int64"
              },
              "flagged_by": {
                "type": "string"
              }
            }
          }
        }
      },
      "ApiPublicUser": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "user_1234567890"
          },
          "email": {
            "type": "string",
            "example": "user@example.com"
          },
          "first_name": {
            "type": "string",
            "nullable": true,
            "example": "Juan"
          },
          "last_name": {
            "type": "string",
            "nullable": true,
            "example": "Pérez"
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "example": "+52 55 1234 5678"
          },
          "teams": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "team_1234567890"
            ]
          },
          "created_at": {
            "type": "number",
            "example": 1677651234
          },
          "company_role": {
            "type": "string",
            "nullable": true,
            "example": "CEO"
          },
          "address": {
            "type": "object",
            "nullable": true,
            "properties": {
              "city": {
                "type": "string",
                "nullable": true,
                "example": "Ciudad de México"
              },
              "country": {
                "type": "string",
                "nullable": true,
                "example": "MEX"
              },
              "state": {
                "type": "string",
                "nullable": true,
                "example": "CDMX"
              }
            }
          }
        }
      },
      "ApiPublicWebhook": {
        "type": "object",
        "required": [
          "id",
          "url",
          "events",
          "status",
          "owner",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "wh_dyS2ZVTj",
            "description": "Unique webhook identifier"
          },
          "url": {
            "type": "string",
            "format": "url",
            "example": "https://your-domain.com/webhooks/gigstack",
            "description": "Endpoint URL that receives the events. Any valid URL is accepted; use HTTPS in production"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "payment.created",
                "payment.updated",
                "payment.succeeded",
                "payment.canceled",
                "payment.deleted",
                "payment.upcoming_due_date",
                "invoice.created",
                "invoice.canceled",
                "invoice.failed",
                "invoice_batch.completed",
                "receipt.created",
                "receipt.updated",
                "receipt.completed",
                "receipt.deleted",
                "customer.created",
                "customer.updated",
                "customer.deleted",
                "service.created",
                "service.updated",
                "service.deleted",
                "sat.invoice.synced"
              ]
            },
            "example": [
              "payment.created",
              "payment.succeeded",
              "invoice.created"
            ],
            "description": "Array of event types to subscribe to"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ],
            "example": "active",
            "description": "Webhook status - active or inactive"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Production payment notifications",
            "description": "Optional description of the webhook purpose"
          },
          "owner": {
            "type": "string",
            "example": "8UWdgXELUhf022vuoq249mtGytG2",
            "description": "User ID who created the webhook"
          },
          "created_at": {
            "type": "number",
            "example": 1709090576567,
            "description": "Unix timestamp (milliseconds) of webhook creation"
          }
        }
      },
      "WebhookInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`) — body\nvalidation runs in strict allowlist mode. `team`, `livemode` and `owner` are reserved\nand injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "url",
          "events"
        ],
        "properties": {
          "url": {
            "description": "Endpoint URL that receives the events. Any valid URL is accepted; use HTTPS in production",
            "example": "https://your-domain.com/webhooks/gigstack",
            "type": "string",
            "format": "uri"
          },
          "events": {
            "description": "Array of event types to subscribe to (at least one required)",
            "example": [
              "payment.created",
              "payment.succeeded"
            ],
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "payment.created",
                "payment.updated",
                "payment.succeeded",
                "payment.canceled",
                "payment.deleted",
                "payment.upcoming_due_date",
                "invoice.created",
                "invoice.canceled",
                "invoice.failed",
                "invoice_batch.completed",
                "receipt.created",
                "receipt.updated",
                "receipt.completed",
                "receipt.deleted",
                "customer.created",
                "customer.updated",
                "customer.deleted",
                "service.created",
                "service.updated",
                "service.deleted",
                "sat.invoice.synced"
              ]
            },
            "minItems": 1
          },
          "description": {
            "description": "Optional description of the webhook purpose",
            "example": "Production webhook for payment events",
            "type": "string",
            "nullable": true
          },
          "status": {
            "description": "Webhook status - defaults to active",
            "example": "active",
            "default": "active",
            "type": "string",
            "enum": [
              "active",
              "inactive",
              null
            ],
            "nullable": true
          }
        }
      },
      "WebhookUpdateInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`) — body\nvalidation runs in strict allowlist mode. `team`, `livemode` and `owner` are reserved\nand injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "url": {
            "description": "HTTPS endpoint URL to receive webhook events",
            "example": "https://new-domain.com/webhooks/gigstack",
            "type": "string",
            "format": "uri"
          },
          "events": {
            "description": "Array of event types to subscribe to",
            "example": [
              "payment.created",
              "payment.succeeded",
              "invoice.created"
            ],
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "payment.created",
                "payment.updated",
                "payment.succeeded",
                "payment.canceled",
                "payment.deleted",
                "payment.upcoming_due_date",
                "invoice.created",
                "invoice.canceled",
                "invoice.failed",
                "invoice_batch.completed",
                "receipt.created",
                "receipt.updated",
                "receipt.completed",
                "receipt.deleted",
                "customer.created",
                "customer.updated",
                "customer.deleted",
                "service.created",
                "service.updated",
                "service.deleted",
                "sat.invoice.synced"
              ]
            },
            "minItems": 1
          },
          "description": {
            "description": "Optional description of the webhook purpose",
            "example": "Updated webhook description",
            "type": "string",
            "nullable": true
          },
          "status": {
            "description": "Webhook status - active or inactive",
            "example": "inactive",
            "type": "string",
            "enum": [
              "active",
              "inactive",
              null
            ],
            "nullable": true
          }
        }
      },
      "TeamInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`) — body\nvalidation runs in strict allowlist mode. `team`, `livemode` and `owner` are reserved\nand injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "address": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "country"
            ],
            "properties": {
              "country": {
                "example": "MEX",
                "type": "string"
              },
              "street": {
                "example": "Av. Insurgentes Sur",
                "type": "string",
                "nullable": true
              },
              "zip": {
                "example": "03100",
                "type": "string",
                "nullable": true
              },
              "city": {
                "example": "Ciudad de México",
                "type": "string",
                "nullable": true
              },
              "state": {
                "example": "CDMX",
                "type": "string",
                "nullable": true
              },
              "exterior": {
                "example": "123",
                "type": "string",
                "nullable": true
              },
              "interior": {
                "example": "4B",
                "type": "string",
                "nullable": true
              },
              "municipality": {
                "example": "Benito Juárez",
                "type": "string",
                "nullable": true
              },
              "neighborhood": {
                "example": "Del Valle",
                "type": "string",
                "nullable": true
              }
            },
            "nullable": true
          },
          "brand": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "alias"
            ],
            "properties": {
              "alias": {
                "example": "My Company",
                "type": "string"
              },
              "primary_color": {
                "example": "#FF0000",
                "type": "string",
                "nullable": true
              },
              "secondary_color": {
                "example": "#00FF00",
                "type": "string",
                "nullable": true
              },
              "logo": {
                "example": "https://example.com/logo.png",
                "type": "string",
                "nullable": true
              }
            },
            "nullable": true
          },
          "support_email": {
            "example": "support@company.com",
            "type": "string",
            "nullable": true
          },
          "support_phone": {
            "example": "+52 55 1234 5678",
            "type": "string",
            "nullable": true
          },
          "legal_name": {
            "description": "Legal name of the team/company",
            "example": "Empresa de Tecnología S.A. de C.V.",
            "type": "string",
            "nullable": true
          },
          "tax_id": {
            "example": "ABC123456789",
            "type": "string",
            "nullable": true
          },
          "tax_system": {
            "example": "601",
            "type": "string",
            "nullable": true
          },
          "generate_onboarding_url": {
            "description": "Generate onboarding URL for team setup",
            "example": true,
            "type": "boolean",
            "nullable": true
          },
          "metadata": {
            "description": "Additional metadata to store with the team",
            "type": "object",
            "additionalProperties": true,
            "properties": {},
            "nullable": true
          },
          "add_members": {
            "description": "Array of members to add to the team on creation",
            "example": [
              {
                "id": "user123abc",
                "role": "editor"
              },
              {
                "id": "user456def",
                "role": "admin"
              }
            ],
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id"
              ],
              "properties": {
                "id": {
                  "description": "User ID to add as a team member",
                  "example": "user123abc",
                  "type": "string"
                },
                "role": {
                  "description": "Role for the team member. Defaults to \"viewer\" if not specified.",
                  "example": "editor",
                  "default": "viewer",
                  "type": "string",
                  "nullable": true
                }
              }
            },
            "nullable": true
          },
          "add_master_team_members": {
            "description": "When true, copies all members from the master team to the newly created team with their existing permissions",
            "example": false,
            "type": "boolean",
            "nullable": true
          },
          "credit_limit": {
            "description": "Maximum number of documents (credits) the team can create per billing period. When null or omitted, the team shares the billing account pool with no per-team cap. On update it is applied only when the request is made with an API key of another team of the same billing account (the managing team); a team cannot change its own limit, and the field is ignored in that case.",
            "example": 1000,
            "type": "number",
            "nullable": true
          }
        }
      },
      "TeamSettingsInput": {
        "type": "object",
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`) — body\nvalidation runs in strict allowlist mode. `team`, `livemode` and `owner` are reserved\nand injected by the auth middleware.\n",
        "additionalProperties": false,
        "properties": {
          "keep_full_legal_name": {
            "type": "boolean",
            "nullable": true,
            "example": false,
            "description": "Keep full legal name in documents"
          },
          "default_description": {
            "type": "string",
            "nullable": true,
            "example": "Consulting services",
            "description": "Default description for items"
          },
          "taxes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TeamTaxDefault"
            },
            "nullable": true,
            "description": "Default taxes configuration for MXN invoices. Each object follows the TeamTaxDefault schema (type, rate, factor, inclusive, withholding).",
            "example": [
              {
                "type": "IVA",
                "rate": 0.16,
                "factor": "Tasa",
                "inclusive": false,
                "withholding": false
              }
            ]
          },
          "taxes_usd": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TeamTaxDefault"
            },
            "nullable": true,
            "description": "Default taxes configuration for USD invoices. Each object follows the TeamTaxDefault schema (type, rate, factor, inclusive, withholding).",
            "example": [
              {
                "type": "IVA",
                "rate": 0.16,
                "factor": "Tasa",
                "inclusive": false,
                "withholding": false
              }
            ]
          },
          "emails": {
            "type": "object",
            "nullable": true,
            "properties": {
              "invoices_bcc": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "email"
                },
                "nullable": true,
                "example": [
                  "admin@company.com"
                ],
                "description": "BCC emails for invoices"
              },
              "avoid_invoice_emails": {
                "type": "boolean",
                "nullable": true,
                "example": false,
                "description": "Disable invoice emails"
              },
              "avoid_test_invoice_emails": {
                "type": "boolean",
                "nullable": true,
                "example": true,
                "description": "Disable test invoice emails"
              },
              "avoid_receipts_emails": {
                "type": "boolean",
                "nullable": true,
                "example": false,
                "description": "Disable receipt emails"
              }
            }
          },
          "override_item_description": {
            "type": "string",
            "nullable": true,
            "example": "Professional services",
            "description": "Override description for all items"
          },
          "global_invoice_disabled": {
            "type": "boolean",
            "nullable": true,
            "example": false,
            "description": "Disable global invoice functionality"
          },
          "complements": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "nullable": true,
            "description": "CFDI complements configuration"
          },
          "uses_on_self_invoice_portal": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true,
            "example": [
              "G03",
              "S01"
            ],
            "description": "Available CFDI uses on self-invoice portal"
          },
          "invoice_pdf_notes": {
            "type": "string",
            "nullable": true,
            "example": "Additional notes for PDF invoices",
            "description": "Default notes to include in invoice PDFs"
          },
          "product_key": {
            "type": "string",
            "nullable": true,
            "example": "80141503",
            "description": "Default SAT product key"
          },
          "unit_key": {
            "type": "string",
            "nullable": true,
            "example": "E48",
            "description": "Default SAT unit key"
          },
          "use": {
            "type": "string",
            "nullable": true,
            "example": "G03",
            "description": "Default CFDI use"
          },
          "automate_complement_for_ppd_invoices": {
            "type": "boolean",
            "nullable": true,
            "example": false,
            "description": "Automatically create payment complement for PPD invoices"
          },
          "withholding_taxes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TeamTaxDefault"
            },
            "nullable": true,
            "description": "Withholding taxes configuration (natural persons). Each object follows the TeamTaxDefault schema (type, rate, factor, inclusive, withholding).",
            "example": [
              {
                "type": "ISR",
                "rate": 0.1,
                "factor": "Tasa",
                "withholding": true
              }
            ]
          },
          "periodicity": {
            "type": "string",
            "nullable": true,
            "enum": [
              "day",
              "week",
              "two_weeks",
              "month",
              "two_months",
              null
            ],
            "example": "month",
            "description": "Default billing/invoicing period for the team"
          },
          "default_series": {
            "type": "object",
            "nullable": true,
            "properties": {
              "income": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "serie": {
                    "type": "string",
                    "nullable": true,
                    "example": "A",
                    "description": "Default income series"
                  },
                  "folio_number_live": {
                    "type": "number",
                    "nullable": true,
                    "example": 1001,
                    "description": "Next folio number for live environment"
                  },
                  "folio_number_test": {
                    "type": "number",
                    "nullable": true,
                    "example": 1,
                    "description": "Next folio number for test environment"
                  }
                }
              },
              "complements": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "serie": {
                    "type": "string",
                    "nullable": true,
                    "example": "C",
                    "description": "Default complements series"
                  },
                  "folio_number_live": {
                    "type": "number",
                    "nullable": true,
                    "example": 1001,
                    "description": "Next folio number for live environment"
                  },
                  "folio_number_test": {
                    "type": "number",
                    "nullable": true,
                    "example": 1,
                    "description": "Next folio number for test environment"
                  }
                }
              },
              "credit_note": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "serie": {
                    "type": "string",
                    "nullable": true,
                    "example": "N",
                    "description": "Default credit note series"
                  },
                  "folio_number_live": {
                    "type": "number",
                    "nullable": true,
                    "example": 1001,
                    "description": "Next folio number for live environment"
                  },
                  "folio_number_test": {
                    "type": "number",
                    "nullable": true,
                    "example": 1,
                    "description": "Next folio number for test environment"
                  }
                }
              }
            }
          }
        }
      },
      "UserInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`) — body\nvalidation runs in strict allowlist mode. `team`, `livemode` and `owner` are reserved\nand injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "email": {
            "description": "Required by account creation. On user updates this reserved field is ignored; this endpoint does not change the authentication email.",
            "type": "string",
            "nullable": true
          },
          "first_name": {
            "example": "John",
            "type": "string",
            "nullable": true
          },
          "last_name": {
            "example": "Doe",
            "type": "string",
            "nullable": true
          },
          "phone": {
            "example": "+52 55 1234 5678",
            "type": "string",
            "nullable": true
          },
          "company_role": {
            "example": "Manager",
            "type": "string",
            "nullable": true
          },
          "address": {
            "description": "User address information. Note: municipality field is accepted in requests but not returned in responses.",
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "country": {
                "example": "MEX",
                "type": "string",
                "nullable": true
              },
              "street": {
                "example": "Av. Insurgentes Sur",
                "type": "string",
                "nullable": true
              },
              "zip": {
                "example": "03100",
                "type": "string",
                "nullable": true
              },
              "city": {
                "example": "Ciudad de México",
                "type": "string",
                "nullable": true
              },
              "state": {
                "example": "CDMX",
                "type": "string",
                "nullable": true
              },
              "exterior": {
                "example": "123",
                "type": "string",
                "nullable": true
              },
              "municipality": {
                "description": "Municipality name (accepted in requests, stored in database, but not returned in responses)",
                "example": "Benito Juárez",
                "type": "string",
                "nullable": true
              },
              "neighborhood": {
                "example": "Del Valle",
                "type": "string",
                "nullable": true
              }
            },
            "nullable": true
          },
          "auto_join": {
            "description": "If true, automatically adds the user to the team associated with the API key. Defaults to false if not specified. When true and role is specified, the user will be added with that role.",
            "example": true,
            "type": "boolean"
          },
          "role": {
            "description": "Role to assign to the user when auto_join is true. Can be \"editor\", \"admin\", or \"viewer\". Defaults to \"viewer\" if not specified. This parameter works in conjunction with auto_join - when auto_join is true, the user will be added to the team with the specified role.",
            "example": "viewer",
            "type": "string"
          }
        }
      },
      "ReceiptInput": {
        "description": "Unknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`);\n`metadata` is the one object that accepts arbitrary keys. `team`, `livemode` and\n`owner` are reserved and injected by the auth middleware.\n",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "client",
          "currency",
          "items"
        ],
        "properties": {
          "client": {
            "$ref": "#/components/schemas/EmbeddedClientInput"
          },
          "currency": {
            "description": "Currency code (ISO 4217)",
            "example": "MXN",
            "type": "string"
          },
          "exchange_rate": {
            "description": "Exchange rate to use for currency conversion",
            "example": 1,
            "type": "number",
            "nullable": true
          },
          "items": {
            "description": "Receipt items",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSchema"
            }
          },
          "metadata": {
            "description": "Additional metadata - accepts any custom properties for tracking business data, references, or integration identifiers. All properties are preserved and returned as-is.",
            "type": "object",
            "additionalProperties": true,
            "properties": {},
            "nullable": true
          },
          "periodicity": {
            "description": "Receipt validity period. `two_month` and `two_months` are both accepted and\nmean the same period (end of the following month).\n",
            "example": "month",
            "type": "string",
            "enum": [
              "day",
              "week",
              "two_weeks",
              "month",
              "two_month",
              "two_months",
              null
            ],
            "nullable": true
          },
          "invoice_config": {
            "description": "Invoice configuration for future stamping. Accepted and validated on this\nendpoint, but note the create-receipt handler does **not** currently persist it\nonto the receipt — it is validated and discarded.\n",
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "folio": {
                "type": "number",
                "nullable": true
              },
              "serie": {
                "type": "string",
                "nullable": true
              },
              "date": {
                "type": "number",
                "nullable": true
              },
              "global": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "year": {
                    "type": "number",
                    "nullable": true
                  },
                  "months": {
                    "type": "string",
                    "nullable": true
                  },
                  "periodicity": {
                    "type": "string",
                    "nullable": true
                  }
                },
                "nullable": true
              },
              "validUntil": {
                "type": "number",
                "nullable": true
              }
            }
          },
          "payment_form": {
            "description": "SAT payment form code",
            "example": "01",
            "type": "string",
            "nullable": true
          },
          "idempotency_key": {
            "description": "Stable key for one business event. A duplicate returns HTTP 400 with error.code resource_conflict, not the existing receipt as a successful response. Reconcile the existing record and retain this key across retries.",
            "example": "receipt-key-12345",
            "type": "string",
            "nullable": true
          },
          "send_email": {
            "description": "Whether to send email and WhatsApp notifications for this receipt. Defaults to `true`.",
            "example": true,
            "type": "boolean",
            "nullable": true
          },
          "ignore_emails": {
            "description": "Suppress email and WhatsApp notifications for this receipt. Takes precedence\nover `send_email` — the handler stores `ignore_emails ?? (send_email === false)`.\n",
            "example": false,
            "type": "boolean",
            "nullable": true
          }
        }
      },
      "DocumentTypeEnum": {
        "type": "string",
        "enum": [
          "contract",
          "delivery_proof",
          "payment_proof",
          "communication"
        ],
        "example": "contract",
        "description": "Kind of supporting document. Only these four values are accepted when creating a\ndocument. The internal type union also contains `payment_confirmation`,\n`subscription_info`, `usage_report` and `cronograma`, but those cannot be set through\nthis API.\n"
      },
      "DocumentComplianceStatusEnum": {
        "type": "string",
        "enum": [
          "pending_review",
          "valid",
          "requires_update",
          "expired",
          "rejected"
        ],
        "example": "pending_review",
        "description": "Compliance review state. Always `pending_review` when a document is created; change it\nwith `PATCH /v2/documents/{id}`.\n"
      },
      "DocumentLinkEntityTypeEnum": {
        "type": "string",
        "enum": [
          "invoice",
          "payment",
          "receipt",
          "client"
        ],
        "example": "invoice",
        "description": "Kind of gigstack entity a document can be linked to."
      },
      "DocumentInput": {
        "type": "object",
        "description": "Metadata for a document that has already been uploaded to storage. Unknown top-level\nkeys are rejected; `metadata` is the one object that accepts arbitrary keys.\n`complianceStatus` cannot be set here — it is always `pending_review` on create.\n",
        "additionalProperties": false,
        "required": [
          "documentType",
          "name",
          "fileUrl",
          "storagePath",
          "fileName"
        ],
        "properties": {
          "documentType": {
            "$ref": "#/components/schemas/DocumentTypeEnum"
          },
          "name": {
            "type": "string",
            "example": "Contrato de servicios 2026 — Cliente ACME"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Contrato marco de prestación de servicios"
          },
          "fileUrl": {
            "type": "string",
            "description": "Publicly resolvable URL of the stored file.",
            "example": "https://storage.googleapis.com/gigstack-docs/team_123/contrato-acme.pdf"
          },
          "storagePath": {
            "type": "string",
            "description": "Path of the object inside the storage bucket.",
            "example": "teams/team_123/documents/contrato-acme.pdf"
          },
          "fileName": {
            "type": "string",
            "example": "contrato-acme.pdf"
          },
          "fileSize": {
            "type": "number",
            "nullable": true,
            "description": "Size in bytes.",
            "example": 284913
          },
          "mimeType": {
            "type": "string",
            "nullable": true,
            "example": "application/pdf"
          },
          "linkedEntities": {
            "type": "array",
            "nullable": true,
            "description": "Entities to link the document to at creation time.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "entityType",
                "entityId"
              ],
              "properties": {
                "entityType": {
                  "$ref": "#/components/schemas/DocumentLinkEntityTypeEnum"
                },
                "entityId": {
                  "type": "string",
                  "example": "client_1234567890"
                }
              }
            }
          },
          "validFrom": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Start of the document's validity window, epoch **milliseconds**.",
            "example": 1767225600000
          },
          "validUntil": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "End of the document's validity window, epoch **milliseconds**.",
            "example": 1798761600000
          },
          "tags": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "example": [
              "contrato",
              "acme"
            ]
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "analyzeWithAI": {
            "type": "boolean",
            "nullable": true,
            "description": "Request AI extraction as part of creation.",
            "example": false
          }
        }
      },
      "DocumentUpdateInput": {
        "type": "object",
        "description": "Partial update. Every field is optional and only the keys present in the body are\nwritten. The file itself (`documentType`, `fileUrl`, `storagePath`, `fileName`) is\nimmutable and those keys are rejected as unknown.\n",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "example": "Contrato de servicios 2026 — Cliente ACME (v2)"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "complianceStatus": {
            "$ref": "#/components/schemas/DocumentComplianceStatusEnum"
          },
          "complianceNotes": {
            "type": "string",
            "nullable": true,
            "example": "Revisado por el área fiscal."
          },
          "validFrom": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": 1767225600000
          },
          "validUntil": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": 1798761600000
          },
          "tags": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "example": [
              "contrato",
              "revisado"
            ]
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          }
        }
      },
      "DocumentLinkInput": {
        "type": "object",
        "description": "Identifies the entity a document should be linked to or unlinked from.",
        "additionalProperties": false,
        "required": [
          "entityType",
          "entityId"
        ],
        "properties": {
          "entityType": {
            "$ref": "#/components/schemas/DocumentLinkEntityTypeEnum"
          },
          "entityId": {
            "type": "string",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          }
        }
      },
      "ApiPublicDocument": {
        "type": "object",
        "description": "A document as returned by the documents endpoints (snake_case).",
        "properties": {
          "id": {
            "type": "string",
            "example": "doc_1234567890"
          },
          "document_type": {
            "$ref": "#/components/schemas/DocumentTypeEnum"
          },
          "name": {
            "type": "string",
            "example": "Contrato de servicios 2026 — Cliente ACME"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "file_url": {
            "type": "string",
            "example": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_123%2Fdocuments%2Fcontrato-acme.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43"
          },
          "file_name": {
            "type": "string",
            "example": "contrato-acme.pdf"
          },
          "file_size": {
            "type": "number",
            "nullable": true,
            "example": 284913
          },
          "mime_type": {
            "type": "string",
            "nullable": true,
            "example": "application/pdf"
          },
          "linked_entities": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "entity_type": {
                  "$ref": "#/components/schemas/DocumentLinkEntityTypeEnum"
                },
                "entity_id": {
                  "type": "string",
                  "example": "client_1234567890"
                },
                "linked_at": {
                  "type": "integer",
                  "format": "int64",
                  "example": 1767225600000
                }
              }
            }
          },
          "compliance_status": {
            "$ref": "#/components/schemas/DocumentComplianceStatusEnum"
          },
          "compliance_notes": {
            "type": "string",
            "nullable": true
          },
          "valid_from": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": 1767225600000
          },
          "valid_until": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": 1798761600000
          },
          "ai_extraction": {
            "type": "object",
            "nullable": true,
            "description": "Result of the last AI analysis. `null` until the document is analyzed.",
            "properties": {
              "extracted_at": {
                "type": "integer",
                "format": "int64",
                "example": 1767225600000
              },
              "model": {
                "type": "string",
                "example": "gemini-2.5-flash"
              },
              "confidence": {
                "type": "number",
                "example": 0.92
              },
              "extracted_data": {
                "type": "object",
                "additionalProperties": true,
                "description": "Fields extracted from the document; the shape depends on `document_type`."
              }
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "contrato",
              "acme"
            ]
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "example": 1767225600000
          },
          "created_by": {
            "type": "string",
            "example": "user_1234567890"
          },
          "updated_at": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "example": 1767225600000
          },
          "livemode": {
            "type": "boolean",
            "example": true
          }
        }
      },
      "ApiPublicSearch": {
        "type": "object",
        "required": [
          "on_key",
          "on_value",
          "auto_create"
        ],
        "properties": {
          "on_key": {
            "type": "string",
            "example": "tax_id",
            "description": "Field to search on"
          },
          "on_value": {
            "type": "string",
            "example": "PEGJ800101ABC",
            "description": "Value to search for"
          },
          "auto_create": {
            "type": "boolean",
            "example": true,
            "description": "Whether to create the resource if not found"
          },
          "safety_check": {
            "type": "boolean",
            "example": false,
            "description": "When true, prevents using multiple matching results (returns error). When false, uses the first result found. Default: false"
          }
        }
      },
      "ApiPublicThirdParty": {
        "type": "object",
        "required": [
          "legal_name",
          "tax_id",
          "tax_system",
          "zip"
        ],
        "properties": {
          "legal_name": {
            "type": "string",
            "example": "Third Party SA de CV",
            "description": "Legal name of the third party"
          },
          "tax_id": {
            "type": "string",
            "example": "TPR800101ABC",
            "description": "RFC (Tax ID) of the third party"
          },
          "tax_system": {
            "type": "string",
            "example": "601",
            "description": "SAT tax system code"
          },
          "zip": {
            "type": "string",
            "example": "03100",
            "description": "Postal code of the third party"
          }
        }
      },
      "ApiPublicInvoiceConfig": {
        "type": "object",
        "properties": {
          "serie": {
            "type": "string",
            "nullable": true,
            "example": "A",
            "description": "Invoice series"
          },
          "folio": {
            "type": "string",
            "nullable": true,
            "example": "123",
            "description": "Invoice folio number"
          }
        }
      },
      "ApiPublicRefund": {
        "type": "object",
        "required": [
          "id",
          "reason",
          "created_at",
          "total"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "refund_1234567890",
            "description": "Unique refund identifier"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiPublicService"
            },
            "nullable": true,
            "description": "Items being refunded"
          },
          "reason": {
            "type": "string",
            "example": "Customer requested cancellation",
            "description": "Reason for the refund"
          },
          "created_at": {
            "type": "number",
            "example": 1677651234,
            "description": "Unix timestamp of when the refund was created"
          },
          "total": {
            "type": "number",
            "example": 1160,
            "description": "Total refund amount"
          }
        }
      },
      "TeamTaxDefault": {
        "type": "object",
        "required": [
          "type",
          "rate"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "IVA",
              "ISR",
              "IEPS"
            ],
            "example": "IVA",
            "description": "Type of tax"
          },
          "rate": {
            "type": "number",
            "example": 0.16,
            "description": "Tax rate (e.g., 0.16 for 16% IVA)"
          },
          "factor": {
            "type": "string",
            "nullable": true,
            "example": "Tasa",
            "description": "SAT tax factor (Tasa, Cuota, Exento)"
          },
          "inclusive": {
            "type": "boolean",
            "nullable": true,
            "example": false,
            "description": "Whether the tax is included in the unit price"
          },
          "withholding": {
            "type": "boolean",
            "nullable": true,
            "example": false,
            "description": "Whether this is a withholding tax"
          }
        }
      },
      "TaxElement": {
        "type": "object",
        "required": [
          "type",
          "rate"
        ],
        "properties": {
          "base": {
            "oneOf": [
              {
                "type": "number",
                "nullable": true
              },
              {
                "type": "string",
                "nullable": true
              }
            ],
            "example": 100,
            "description": "Taxable base amount. Accepts number or numeric string. If null, calculated automatically from item price."
          },
          "factor": {
            "type": "string",
            "nullable": true,
            "example": "Tasa",
            "description": "SAT tax factor (Tasa, Cuota, Exento)"
          },
          "inclusive": {
            "type": "boolean",
            "nullable": true,
            "example": false,
            "description": "Whether the tax is included in the unit price"
          },
          "rate": {
            "type": "number",
            "example": 0.16,
            "description": "Tax rate (e.g., 0.16 for 16% IVA)"
          },
          "type": {
            "type": "string",
            "enum": [
              "IVA",
              "ISR",
              "IEPS"
            ],
            "example": "IVA",
            "description": "Type of tax"
          },
          "withholding": {
            "type": "boolean",
            "nullable": true,
            "example": false,
            "description": "Whether this is a withholding tax"
          }
        }
      },
      "ClientAddress": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "country": {
            "example": "MEX",
            "type": "string",
            "nullable": true,
            "maxLength": 3
          },
          "street": {
            "example": "Av. Insurgentes Sur",
            "type": "string",
            "nullable": true
          },
          "zip": {
            "example": "03100",
            "type": "string",
            "nullable": true
          },
          "city": {
            "example": "Ciudad de México",
            "type": "string",
            "nullable": true
          },
          "state": {
            "example": "CDMX",
            "type": "string",
            "nullable": true
          },
          "exterior": {
            "example": "123",
            "type": "string",
            "nullable": true
          },
          "interior": {
            "example": "4B",
            "type": "string",
            "nullable": true
          },
          "municipality": {
            "example": "Benito Juárez",
            "type": "string",
            "nullable": true
          },
          "neighborhood": {
            "example": "Del Valle",
            "type": "string",
            "nullable": true
          }
        }
      },
      "TaxSchema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "base": {
            "description": "Taxable base amount. Accepts number or numeric string. If null, calculated automatically from item price.",
            "example": 100,
            "oneOf": [
              {
                "type": "number",
                "nullable": true
              },
              {
                "type": "string",
                "description": "Numeric string accepted by the request validator."
              }
            ]
          },
          "factor": {
            "example": "Tasa",
            "type": "string",
            "nullable": true
          },
          "inclusive": {
            "example": false,
            "type": "boolean",
            "nullable": true
          },
          "rate": {
            "example": 0.16,
            "type": "number",
            "nullable": true
          },
          "type": {
            "example": "IVA",
            "type": "string",
            "enum": [
              "IVA",
              "ISR",
              "IEPS",
              null
            ],
            "nullable": true
          },
          "withholding": {
            "example": false,
            "type": "boolean",
            "nullable": true
          }
        }
      },
      "StandardSuccessResponse": {
        "type": "object",
        "description": "Standardized success envelope emitted by `sendSuccessResponse`.\n",
        "required": [
          "success",
          "data",
          "timestamp"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ],
            "example": true
          },
          "data": {
            "type": "object",
            "description": "The operation payload."
          },
          "message": {
            "type": "string",
            "description": "Human-readable summary. Present only when the handler supplies one.",
            "example": "Operation completed successfully"
          },
          "timestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Server time in **epoch milliseconds** (`Luxon.now().toMillis()`).",
            "example": 1767225600000
          }
        }
      },
      "StandardErrorResponse": {
        "type": "object",
        "description": "Standardized error envelope emitted by `sendErrorResponse` and its helpers\n(`sendValidationError`, `sendNotFoundError`, `sendUnauthorizedError`,\n`sendForbiddenError`, `sendConflictError`, `sendBadRequestError`,\n`sendInternalServerError`).\n",
        "required": [
          "success",
          "error",
          "timestamp"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              false
            ],
            "example": false
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable code. Values emitted by the shared helpers:\n`unauthorized`, `forbidden`, `invalid_token`, `validation_failed`,\n`invalid_request_body`, `missing_required_field`, `invalid_field_value`,\n`resource_not_found`, `resource_already_exists`, `resource_conflict`,\n`business_rule_violation`, `operation_not_allowed`,\n`insufficient_permissions`, `external_service_error`,\n`payment_processor_error`, `cfdi_service_error`,\n`internal_server_error`, `service_unavailable`, `rate_limit_exceeded`,\n`database_error`, `data_integrity_error`, `file_not_found`,\n`file_upload_error`, `invalid_file_format`. Individual handlers may\nemit additional endpoint-specific codes, documented per operation.\n",
                "example": "validation_failed"
              },
              "message": {
                "type": "string",
                "example": "Request validation failed"
              },
              "details": {
                "oneOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                ],
                "description": "Present only when the handler supplies detail. Validation failures\nemit an array of `\"<field path>: <message>\"` strings.\n",
                "example": [
                  "currency: Field is required"
                ]
              }
            }
          },
          "timestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Server time in epoch milliseconds.",
            "example": 1767225600000
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "description": "Raw (non-enveloped) health probe body. Health routes bypass the auth chain entirely.\n",
        "required": [
          "status",
          "module"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ],
            "example": "ok"
          },
          "module": {
            "type": "string",
            "example": "clients"
          }
        }
      },
      "CfdiErrorResponse": {
        "type": "object",
        "description": "Raw CFDI/PAC error body produced by `handleCFDIError`. **Not** the standardized\nenvelope. On `POST /v2/invoices/income`, `/egress` and `/invoices/draft/{id}/stamp`\nthis object is nested one level deeper, under a `message` key\n(`{ \"message\": { \"error\": …, \"code\": …, \"retryable\": … } }`); on\n`DELETE /v2/invoices/{id}` it is returned at the top level.\n",
        "required": [
          "error",
          "code",
          "retryable"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable Spanish error message shown to the end user.",
            "example": "Error al timbrar la factura: El CSD del emisor no es válido."
          },
          "code": {
            "type": "string",
            "description": "CFDI/PAC error code: a SAT/PAC code (e.g. `CFDI40147`) or one of gigstack's own\n(`SAT_NOT_CONNECTED`, `CSD_VALIDATION_ERROR`, `PAC_UNAVAILABLE`, `PAC_OUTCOME_UNKNOWN`,\n`STAMP_NEEDS_REVIEW`, `INVALID_INVOICE`, `STAMPING_ERROR`, …).\n",
            "example": "CSD_VALIDATION_ERROR"
          },
          "providerMessage": {
            "type": "string",
            "description": "Raw message returned by the PAC. Only present on generic (400) stamping failures.",
            "example": "CFDI40147 - El campo UsoCFDI no es válido"
          },
          "retryable": {
            "type": "boolean",
            "description": "Whether sending the **same** request again is safe and can succeed. `true` for `503`\n`PAC_UNAVAILABLE`, and for `503` `PAC_OUTCOME_UNKNOWN` only when the request carried an\n`idempotency_key`. Every `400`, `409` and `412` is `false`.\n",
            "example": false
          },
          "duplicate": {
            "type": "boolean",
            "description": "Present and `true` only on the `400` answered for an `idempotency_key` whose invoice already\nexists. Nothing was stamped or charged by this request; `uuid` names the existing invoice.\n",
            "example": true
          },
          "uuid": {
            "type": "string",
            "description": "With `duplicate`, the folio fiscal (UUID) of the invoice already issued under this `idempotency_key`.",
            "example": "0f8fad5b-d9cb-469f-a165-70867728950e"
          }
        }
      },
      "CreditLimitResponse": {
        "type": "object",
        "description": "Raw credit-limit body (HTTP 429) returned by invoice income creation and draft\nstamping. Not the standardized envelope.\n",
        "required": [
          "message",
          "error"
        ],
        "properties": {
          "message": {
            "type": "string",
            "example": "Team credit limit reached"
          },
          "error": {
            "type": "string",
            "description": "Reason reported by the credit checker.",
            "example": "Credit limit of 100 documents reached for this billing period"
          },
          "credit_limit": {
            "type": "number",
            "example": 100
          },
          "used_credits": {
            "type": "number",
            "example": 100
          }
        }
      },
      "ListResponse": {
        "type": "object",
        "description": "Response shape of the Firestore-backed list handlers. Note this is **not** the\nstandardized envelope: `data` sits at the top level alongside the pagination keys and\n`message`/`success`/`timestamp`, rather than under a `data` wrapper.\n\nA few modules (clients, payments) take a **second code path** when the request carries\n`metadata.*` / `metadata_*` filters and the team has Typesense configured: Typesense\nresolves the matching ids and the documents are then re-read from Firestore. That path\nreturns `has_more`, `total_results`, `page` and `per_page` instead of the cursor-style\n`next`. Modules without a Typesense branch (invoices list, receipts, retentions, users)\nonly ever return the cursor form.\n\nFull-text `/search` endpoints are different again — see `SearchResponse`.\n",
        "required": [
          "message",
          "data",
          "success",
          "timestamp"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ],
            "example": true
          },
          "message": {
            "type": "string",
            "example": "Items retrieved successfully"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "next": {
            "type": "string",
            "nullable": true,
            "description": "Cursor for the next page. Cursor-style (Firestore) path only.",
            "example": "eyJjcmVhdGVkX2F0IjoxNjc3NjUxMjM0fQ=="
          },
          "has_more": {
            "type": "boolean",
            "description": "Metadata-filtered (Typesense-assisted) path only.",
            "example": true
          },
          "total_results": {
            "type": "number",
            "description": "Metadata-filtered (Typesense-assisted) path only.",
            "example": 150
          },
          "page": {
            "type": "integer",
            "description": "Metadata-filtered (Typesense-assisted) path only.",
            "example": 1
          },
          "per_page": {
            "type": "integer",
            "description": "Metadata-filtered (Typesense-assisted) path only.",
            "example": 10
          },
          "timestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Server time in epoch milliseconds.",
            "example": 1767225600000
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "description": "Response shape of the Typesense-backed `/search` endpoints (clients, invoices, payments,\nreceipts). Distinct from `ListResponse`: it reports `found` (total matches) rather than\n`has_more`/`total_results`, and it has no cursor. It is also not the standardized\nenvelope — `data` is top-level.\n\nThese endpoints require both a `q` (or `query`) parameter and a Typesense key configured\non the team; either missing yields `400` with `missing_query` / `missing_typesense_key`.\n",
        "required": [
          "message",
          "data",
          "found",
          "page",
          "per_page",
          "success",
          "timestamp"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ],
            "example": true
          },
          "message": {
            "type": "string",
            "example": "Items searched successfully"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "found": {
            "type": "integer",
            "description": "Total number of matching documents.",
            "example": 15
          },
          "page": {
            "type": "integer",
            "example": 1
          },
          "per_page": {
            "type": "integer",
            "example": 10
          },
          "timestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Server time in epoch milliseconds.",
            "example": 1767225600000
          }
        }
      },
      "ErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/StandardErrorResponse"
          }
        ],
        "description": "Standardized error envelope.",
        "example": {
          "success": false,
          "error": {
            "code": "invalid_request_body",
            "message": "An error occurred"
          },
          "timestamp": 1767225600000
        }
      },
      "ValidationErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/StandardErrorResponse"
          }
        ],
        "description": "Body validation failure. Unknown top-level keys are rejected — the validator runs in\nstrict allowlist mode (`allowUnknown: false`), so a field not declared in the request\nschema produces an `unexpected_key` detail rather than being ignored.\n",
        "example": {
          "success": false,
          "error": {
            "code": "validation_failed",
            "message": "Request validation failed",
            "details": [
              "currency: Field is required",
              "client_id: Unexpected field"
            ]
          },
          "timestamp": 1767225600000
        }
      },
      "UnauthorizedError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/StandardErrorResponse"
          }
        ],
        "example": {
          "success": false,
          "error": {
            "code": "unauthorized",
            "message": "Unauthorized access"
          },
          "timestamp": 1767225600000
        }
      },
      "SatImportJobSummary": {
        "type": "object",
        "description": "A preview or import job over a range of SAT history.",
        "properties": {
          "id": {
            "type": "string",
            "example": "satjob_a1b2c3d4e5"
          },
          "type": {
            "type": "string",
            "enum": [
              "preview",
              "backfill",
              "import"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "completed",
              "failed",
              "cancelled"
            ]
          },
          "params": {
            "type": "object",
            "properties": {
              "startDate": {
                "type": "string",
                "format": "date"
              },
              "endDate": {
                "type": "string",
                "format": "date"
              },
              "directions": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "issued",
                    "received"
                  ]
                }
              }
            }
          },
          "progress": {
            "type": "object",
            "properties": {
              "totalWindows": {
                "type": "integer",
                "description": "One per month per direction"
              },
              "doneWindows": {
                "type": "integer"
              },
              "invoicesFound": {
                "type": "integer"
              },
              "invoicesSaved": {
                "type": "integer"
              },
              "alreadyInGigstack": {
                "type": "integer",
                "description": "Issued CFDIs gigstack already holds, so nothing to buy"
              }
            }
          },
          "aggregates": {
            "type": "object",
            "properties": {
              "byMonth": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "month": {
                      "type": "string",
                      "example": "2026-05"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "totalAmount": {
                      "type": "number"
                    },
                    "nominaCount": {
                      "type": "integer"
                    },
                    "billableCount": {
                      "type": "integer"
                    }
                  }
                }
              },
              "billableCount": {
                "type": "integer",
                "description": "Excludes nómina and anything already held"
              },
              "estimatedCostMxn": {
                "type": "number",
                "description": "billableCount x $0.20 MXN"
              }
            }
          },
          "created_at": {
            "type": "integer"
          },
          "updated_at": {
            "type": "integer"
          },
          "completed_at": {
            "type": "integer",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "NotFoundError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/StandardErrorResponse"
          }
        ],
        "example": {
          "success": false,
          "error": {
            "code": "resource_not_found",
            "message": "Resource not found"
          },
          "timestamp": 1767225600000
        }
      },
      "InternalServerError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/StandardErrorResponse"
          }
        ],
        "example": {
          "success": false,
          "error": {
            "code": "internal_server_error",
            "message": "An internal server error occurred"
          },
          "timestamp": 1767225600000
        }
      },
      "LegacyErrorResponse": {
        "type": "object",
        "description": "Raw error body returned by handlers that do not use the standardized helpers.\nNote the absence of `success` and `timestamp`.\n",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "example": "Invalid body"
          },
          "error": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Present on most, but not all, legacy error paths."
          },
          "errors": {
            "type": "array",
            "description": "Field-level validation errors, when the failure came from body validation.",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string",
                  "example": "client_id"
                },
                "code": {
                  "type": "string",
                  "example": "unexpected_key"
                },
                "message": {
                  "type": "string",
                  "example": "Unexpected field"
                }
              }
            }
          }
        }
      },
      "SatListDefinition": {
        "type": "object",
        "description": "A SAT list tracked by gigstack, plus the metadata of its most recent sync.",
        "properties": {
          "key": {
            "type": "string",
            "description": "Stable identifier for the list.",
            "example": "art_69b_definitivos"
          },
          "label": {
            "type": "string",
            "description": "Human-readable name, as published by the SAT.",
            "example": "Definitivos 69-B"
          },
          "source": {
            "type": "string",
            "description": "Which SAT article the list is published under.",
            "enum": [
              "art_69",
              "art_69b",
              "art_69b_bis"
            ],
            "example": "art_69b"
          },
          "is_risky": {
            "type": "boolean",
            "description": "Whether appearing on this list marks the RFC as risky to invoice.",
            "example": true
          },
          "filename": {
            "type": "string",
            "description": "Name of the source CSV published by the SAT.",
            "example": "Listado_Definitivos.csv"
          },
          "sync": {
            "type": "object",
            "nullable": true,
            "description": "Metadata from the most recent sync. `null` if the list has never completed a sync.",
            "properties": {
              "last_sync_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "last_status": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "ok",
                  "error",
                  null
                ],
                "example": "ok"
              },
              "row_count": {
                "type": "integer",
                "nullable": true,
                "description": "Number of RFCs on the list after the latest sync.",
                "example": 12843
              },
              "previous_row_count": {
                "type": "integer",
                "nullable": true,
                "description": "Row count before the latest sync.",
                "example": 12790
              },
              "net_new": {
                "type": "integer",
                "nullable": true,
                "description": "`row_count` minus `previous_row_count`. Negative when the SAT removed more RFCs than it added.",
                "example": 53
              },
              "removed": {
                "type": "integer",
                "nullable": true,
                "description": "RFCs dropped from the list in the latest sync.",
                "example": 4
              },
              "duration_ms": {
                "type": "integer",
                "nullable": true,
                "example": 8421
              }
            }
          }
        }
      },
      "SatListRfcCheck": {
        "type": "object",
        "description": "Result of checking a single RFC against every SAT list.",
        "properties": {
          "rfc": {
            "type": "string",
            "description": "The RFC that was checked, normalized to uppercase.",
            "example": "XAXX010101000"
          },
          "found": {
            "type": "boolean",
            "description": "Whether the RFC appears on at least one list.",
            "example": true
          },
          "is_risky": {
            "type": "boolean",
            "description": "Whether the RFC appears on at least one list flagged as risky.",
            "example": true
          },
          "risky_lists": {
            "type": "array",
            "description": "Keys of the risky lists the RFC appears on.",
            "items": {
              "type": "string"
            },
            "example": [
              "art_69b_definitivos"
            ]
          },
          "entries": {
            "type": "array",
            "description": "Every matching list entry, risky or not.",
            "items": {
              "type": "object",
              "properties": {
                "list_key": {
                  "type": "string",
                  "example": "art_69b_definitivos"
                },
                "list_label": {
                  "type": "string",
                  "example": "Definitivos 69-B"
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "art_69",
                    "art_69b",
                    "art_69b_bis"
                  ],
                  "example": "art_69b"
                },
                "is_risky": {
                  "type": "boolean",
                  "example": true
                },
                "detail": {
                  "type": "object",
                  "nullable": true,
                  "description": "Extra columns from the SAT CSV for this RFC, when the list publishes them."
                },
                "last_seen_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true,
                  "description": "When the RFC was last seen on this list during a sync."
                }
              }
            }
          }
        }
      },
      "SatOpinion32dCheck": {
        "type": "object",
        "description": "Result of consulting the SAT's public \"Opinión del Cumplimiento\" (32-D) service for a single RFC.\n\nRead `status` carefully: the SAT's public service only ever publishes **positive** opinions, and only\nfor taxpayers who explicitly authorized public disclosure. `no_autorizado` therefore means the result\nis **unknown** — it is not a negative opinion and must never be presented as non-compliance.\n",
        "properties": {
          "rfc": {
            "type": "string",
            "description": "The RFC that was consulted, normalized to uppercase.",
            "example": "EKU9003173C9"
          },
          "status": {
            "type": "string",
            "enum": [
              "positiva",
              "no_autorizado"
            ],
            "description": "- `positiva`: the SAT publishes a positive opinion for this RFC.\n- `no_autorizado`: the SAT publishes nothing for this RFC — either the taxpayer never opted in\n  to public disclosure, or no opinion is published. **Unknown, not negative.**\n",
            "example": "positiva"
          },
          "found": {
            "type": "boolean",
            "description": "Convenience flag — `true` exactly when `status` is `positiva`.",
            "example": true
          },
          "message": {
            "type": "string",
            "nullable": true,
            "description": "The SAT's own informational message, with HTML stripped. Only present when `status` is\n`no_autorizado`; it typically explains that the taxpayer has not authorized publication.\n",
            "example": "El contribuyente no ha autorizado la publicación de su opinión del cumplimiento."
          },
          "pdf_url": {
            "type": "string",
            "nullable": true,
            "description": "URL to download the constancia PDF issued by the SAT. Only present when `status` is\n`positiva`; `null` otherwise. The document is stored per RFC and per day and the link\nis valid for 7 days.\n",
            "example": "https://storage.googleapis.com/gigstackpro.appspot.com/sat-32d/EKU9003173C9/2026-08-06.pdf?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=604800&X-Goog-Signature=2f8c1a..."
          },
          "checked_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix timestamp (ms) of when the SAT was consulted.",
            "example": 1770000000000
          }
        }
      },
      "PaymentFormEnum": {
        "type": "string",
        "enum": [
          "01",
          "02",
          "03",
          "04",
          "05",
          "06",
          "08",
          "12",
          "13",
          "14",
          "15",
          "17",
          "23",
          "24",
          "25",
          "26",
          "27",
          "28",
          "29",
          "30",
          "31",
          "99"
        ],
        "description": "SAT payment form codes (c_FormaPago) according to Mexican tax regulations.\nMost common forms:\n- `01`: Cash (Efectivo)\n- `03`: Electronic funds transfer (Transferencia electrónica)\n- `04`: Credit card (Tarjeta de crédito)\n- `28`: Debit card (Tarjeta de débito)\n",
        "example": "03"
      },
      "ItemSchema": {
        "description": "A line item on an invoice, receipt or payment. Only `quantity` is required; everything\nelse is optional, or resolved from the referenced service when `id`/`search` is used.\n`id` and `search` are mutually exclusive — supplying both is a `400`.\n\nUnknown keys are rejected. Note there is no per-item `metadata` field.\n",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "quantity"
        ],
        "properties": {
          "id": {
            "description": "Service/product ID reference",
            "example": "service_1234567890",
            "type": "string",
            "nullable": true
          },
          "search": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "on_key",
              "on_value"
            ],
            "properties": {
              "on_key": {
                "description": "Field to search on (sku, name, etc.)",
                "example": "sku",
                "type": "string"
              },
              "on_value": {
                "description": "Value to search for",
                "example": "CONS-001",
                "type": "string"
              },
              "auto_create": {
                "description": "Create service if not found",
                "example": true,
                "type": "boolean",
                "nullable": true
              },
              "safety_check": {
                "description": "When true, prevents using multiple matching results (returns error). When false, uses the first result found. Default: false",
                "example": false,
                "type": "boolean",
                "nullable": true
              },
              "update": {
                "type": "boolean",
                "nullable": true
              }
            },
            "nullable": true
          },
          "quantity": {
            "description": "Item quantity",
            "example": 1,
            "type": "number"
          },
          "description": {
            "description": "Item description",
            "example": "Consulting services",
            "type": "string",
            "nullable": true
          },
          "sku": {
            "description": "Stock keeping unit",
            "example": "CONS-001",
            "type": "string",
            "nullable": true
          },
          "product_key": {
            "description": "SAT product key (c_ClaveProdServ)",
            "example": "80141503",
            "type": "string",
            "nullable": true
          },
          "unit_key": {
            "description": "SAT unit key (c_ClaveUnidad)",
            "example": "E48",
            "type": "string",
            "nullable": true
          },
          "unit_name": {
            "description": "Unit name",
            "example": "Servicio",
            "type": "string",
            "nullable": true
          },
          "unit_price": {
            "description": "Unit price",
            "example": 1000,
            "type": "number",
            "nullable": true
          },
          "discount": {
            "description": "Discount amount (absolute value in the item currency, not a percentage)",
            "example": 0,
            "type": "number",
            "nullable": true
          },
          "taxability": {
            "description": "SAT `c_ObjetoImp` — whether the item is subject to tax.",
            "example": "02",
            "type": "string",
            "enum": [
              "01",
              "02",
              "03",
              "04",
              "05",
              "06",
              "07",
              "08",
              null
            ],
            "nullable": true
          },
          "taxes": {
            "description": "Tax elements applied to this item",
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "base": {
                  "description": "Taxable base amount. Accepts number or numeric string. If null, calculated automatically from item price.",
                  "example": 100,
                  "oneOf": [
                    {
                      "type": "number",
                      "nullable": true
                    },
                    {
                      "type": "string",
                      "description": "Numeric string accepted by the request validator."
                    }
                  ]
                },
                "factor": {
                  "description": "SAT tax factor (Tasa, Cuota, Exento)",
                  "example": "Tasa",
                  "type": "string",
                  "nullable": true
                },
                "inclusive": {
                  "description": "Whether the tax is included in the unit price",
                  "example": false,
                  "type": "boolean",
                  "nullable": true
                },
                "rate": {
                  "description": "Tax rate (e.g., 0.16 for 16% IVA)",
                  "example": 0.16,
                  "type": "number",
                  "nullable": true
                },
                "type": {
                  "description": "Type of tax",
                  "example": "IVA",
                  "type": "string",
                  "enum": [
                    "IVA",
                    "ISR",
                    "IEPS",
                    null
                  ],
                  "nullable": true
                },
                "withholding": {
                  "description": "Whether this is a withholding tax",
                  "example": false,
                  "type": "boolean",
                  "nullable": true
                }
              },
              "nullable": true
            }
          },
          "third_party": {
            "description": "Third party information for items provided by external parties",
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "legal_name": {
                "description": "Third party legal name",
                "example": "Third Party SA",
                "type": "string",
                "nullable": true
              },
              "tax_id": {
                "description": "Third party RFC (tax ID)",
                "example": "TPR800101ABC",
                "type": "string",
                "nullable": true
              },
              "tax_system": {
                "description": "Third party tax system",
                "example": "601",
                "type": "string",
                "nullable": true
              },
              "zip": {
                "description": "Third party ZIP code",
                "example": "03100",
                "type": "string",
                "nullable": true
              }
            },
            "nullable": true
          },
          "item_complement": {
            "description": "CFDI item-level complement.",
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "hydrocarbons": {
                "description": "Complemento de hidrocarburos. All four fields are required when this object is present.",
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "permit_type",
                  "permit_number",
                  "fuel_code",
                  "fuel_sub_product"
                ],
                "properties": {
                  "permit_type": {
                    "example": "PL/12345/EXP/ES/2020",
                    "type": "string"
                  },
                  "permit_number": {
                    "example": "12345",
                    "type": "string"
                  },
                  "fuel_code": {
                    "example": "PR03",
                    "type": "string"
                  },
                  "fuel_sub_product": {
                    "example": "10",
                    "type": "string"
                  }
                },
                "nullable": true
              }
            },
            "nullable": true
          }
        }
      },
      "SATDocument": {
        "type": "object",
        "required": [
          "id",
          "document_type",
          "name",
          "file_url",
          "file_name",
          "file_size",
          "mime_type",
          "compliance_status",
          "created_at",
          "linked_entities"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "doc_abc123xyz",
            "description": "Unique document identifier"
          },
          "document_type": {
            "type": "string",
            "enum": [
              "contract",
              "delivery_proof",
              "payment_proof",
              "communication",
              "payment_confirmation",
              "subscription_info",
              "cronograma"
            ],
            "description": "Type of supporting document"
          },
          "name": {
            "type": "string",
            "example": "Service Contract.pdf",
            "description": "Document name"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Main service contract for consulting services",
            "description": "Optional document description"
          },
          "file_url": {
            "type": "string",
            "format": "uri",
            "example": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_1234567890%2Fdocuments%2Fcontrato-2026.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
            "description": "Download URL for the stored file. A Firebase download-token URL, not a public storage link: it does not expire, but treat it as opaque and re-read the resource instead of parsing it."
          },
          "file_name": {
            "type": "string",
            "example": "contract.pdf",
            "description": "Original filename"
          },
          "file_size": {
            "type": "integer",
            "example": 245680,
            "description": "File size in bytes"
          },
          "mime_type": {
            "type": "string",
            "example": "application/pdf",
            "description": "MIME type of the file"
          },
          "compliance_status": {
            "type": "string",
            "enum": [
              "pending_review",
              "valid",
              "requires_update",
              "expired",
              "rejected"
            ],
            "description": "SAT compliance status"
          },
          "compliance_notes": {
            "type": "string",
            "nullable": true,
            "description": "Notes about compliance status"
          },
          "valid_from": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Validity start timestamp (milliseconds)"
          },
          "valid_until": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Validity end timestamp (milliseconds)"
          },
          "ai_extraction": {
            "type": "object",
            "nullable": true,
            "properties": {
              "extracted_at": {
                "type": "integer",
                "format": "int64",
                "description": "Extraction timestamp (milliseconds)"
              },
              "extracted_by": {
                "type": "string",
                "example": "ai",
                "description": "Source of extraction"
              },
              "model": {
                "type": "string",
                "example": "gemini-3-flash",
                "description": "AI model used"
              },
              "confidence": {
                "type": "number",
                "format": "float",
                "example": 0.95,
                "description": "Confidence score (0-1)"
              },
              "extracted_data": {
                "type": "object",
                "additionalProperties": true,
                "description": "Extracted structured data"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Extraction warnings"
              }
            },
            "description": "AI extraction results if analyzed"
          },
          "audits": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "context_type": {
                  "type": "string",
                  "enum": [
                    "invoice",
                    "payment",
                    "receipt"
                  ],
                  "description": "Type of entity audited against"
                },
                "context_id": {
                  "type": "string",
                  "description": "ID of entity audited against"
                },
                "audited_at": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Audit timestamp (milliseconds)"
                },
                "result": {
                  "type": "string",
                  "enum": [
                    "valid",
                    "warning",
                    "mismatch"
                  ],
                  "description": "Audit result"
                },
                "summary": {
                  "type": "string",
                  "description": "Audit summary"
                },
                "details": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "Detailed audit results"
                }
              }
            },
            "description": "Context-specific audit results"
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "example": 1677651234000,
            "description": "Creation timestamp (milliseconds)"
          },
          "created_by": {
            "type": "string",
            "example": "user_abc123",
            "description": "User who created the document"
          },
          "updated_at": {
            "type": "integer",
            "format": "int64",
            "example": 1677651234000,
            "description": "Last update timestamp (milliseconds)"
          },
          "linked_entities": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "entity_type": {
                  "type": "string",
                  "enum": [
                    "invoice",
                    "payment",
                    "receipt",
                    "client"
                  ],
                  "description": "Type of linked entity"
                },
                "entity_id": {
                  "type": "string",
                  "description": "ID of linked entity"
                },
                "linked_at": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Link timestamp (milliseconds)"
                }
              }
            },
            "description": "Entities this document is linked to"
          }
        }
      },
      "UploadSupportDocumentInput": {
        "type": "object",
        "required": [
          "file",
          "documentType"
        ],
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "description": "The file to upload (PDF or image, max 10MB)"
          },
          "documentType": {
            "type": "string",
            "enum": [
              "contract",
              "delivery_proof",
              "payment_proof",
              "communication",
              "payment_confirmation",
              "subscription_info"
            ],
            "description": "Type of supporting document"
          },
          "name": {
            "type": "string",
            "example": "Service Contract",
            "description": "Optional custom name for the document"
          },
          "description": {
            "type": "string",
            "example": "Master services agreement for 2026",
            "description": "Optional description of the document"
          }
        }
      },
      "PlatformPayoutRunStatusEnum": {
        "type": "string",
        "description": "Where a platform payouts run is in its lifecycle.\n\n- `planning` - the files are being read and the plan computed. Normally only seen by a retry\n  that arrives while the first request is still working.\n- `plan_ready` - the plan is computed and waiting for `POST /platform-payouts/{id}/confirm`.\n- `plan_failed` - the plan could not be computed (see `error`). Terminal: upload corrected files\n  under a **new** `Idempotency-Key`.\n- `stamping` - confirmed; the background worker is issuing the CFDIs.\n- `completed` - the worker has nothing left to try. This says nothing about how much was issued:\n  read the run's `result` (`completed`, `partially_completed` or `failed`) to know how it went.\n- `failed` - the worker stopped the whole run (see `error`), for example because the master team\n  no longer has seals (CSD) or the run made no progress after repeated attempts.\n",
        "enum": [
          "planning",
          "plan_ready",
          "plan_failed",
          "stamping",
          "completed",
          "failed"
        ],
        "example": "plan_ready"
      },
      "PlatformPayoutRunResultEnum": {
        "type": "string",
        "nullable": true,
        "description": "How a finished run turned out. `null` while the run is not finished (`planning`, `plan_ready`,\n`plan_failed`, `stamping`). Read this, not `status`, to know how a run went:\n\n- `completed` - no document failed: everything planned was issued.\n- `partially_completed` - some documents failed and at least one was issued.\n- `failed` - the run itself failed (`status: failed`), or it finished having issued nothing while\n  something failed.\n\nCounted as: failures = `progress.failed_count` (movements with at least one failed document) +\n`progress.commission_failed_count`; issued = `income_invoices_count` + `certificates_count` +\n`commission_invoices_count`.\n",
        "enum": [
          "completed",
          "partially_completed",
          "failed",
          null
        ],
        "example": "partially_completed"
      },
      "PlatformPayoutExclusionCode": {
        "type": "string",
        "description": "Stable code for why a document is not planned, sent next to the Spanish sentence. Codes are never\nrenamed; the sentences may be reworded at any time, so branch on the code. New codes may be added.\n\n- `invalid_row` - the row itself is malformed (bad date, amount or month).\n- `provider_not_found` - no gigstack team of the billing account matches the provider.\n- `missing_tax_id` - no RFC (on the team or in the file; for the commission invoice, in the file).\n- `missing_legal_name` - the provider's team has no legal name (certificate: neither team nor file).\n- `missing_zip` - the provider's team has no fiscal zip code.\n- `missing_fiscal_data` - commission invoice: no provider team, or it lacks legal name or fiscal zip.\n- `csd_expired` - the provider's CSD (sellos) in gigstack expired.\n- `missing_csd` - the provider's team has no CSD in gigstack.\n- `tax_system_not_allowed` - the provider's tax regime is not allowed by the account's tax policy.\n- `duplicate_tax_id` - the RFC matches more than one team of the billing account.\n- `name_mismatch` - `Nombre del proveedor` differs from the team's legal name (SAT registry check).\n- `missing_series` - the issuing team has no invoice series (the provider's for income, the master's\n  for commissions).\n- `public_general_not_allowed` - the certificate would need the generic RFC and the policy forbids\n  issuing to the general public.\n- `certificate_month_reserved` - an earlier run already certified this provider-month.\n- `missing_commission` - no commission for the month, so the certificate would be rejected (SPT147).\n- `zero_commission` - the month's commission in the commissions file is zero.\n",
        "enum": [
          "invalid_row",
          "provider_not_found",
          "missing_tax_id",
          "missing_legal_name",
          "missing_zip",
          "missing_fiscal_data",
          "csd_expired",
          "missing_csd",
          "tax_system_not_allowed",
          "duplicate_tax_id",
          "name_mismatch",
          "missing_series",
          "public_general_not_allowed",
          "certificate_month_reserved",
          "missing_commission",
          "zero_commission"
        ],
        "example": "missing_csd"
      },
      "PlatformPayoutRunCreateInput": {
        "type": "object",
        "description": "The two files a run is built from. Each is read by its **extension** (the MIME type is ignored):\n`.csv` / `.txt` as comma-separated text, `.xlsx` / `.xls` / `.xlsm` as a workbook, of which only\nthe first sheet is read. The first row is the header. Headers are matched ignoring case, accents\nand repeated spaces; extra columns are ignored.\n",
        "required": [
          "movements_file",
          "commissions_file"
        ],
        "properties": {
          "movements_file": {
            "type": "string",
            "format": "binary",
            "description": "One row per payout to a provider. Max 5 MB, max 50,000 rows. Required columns:\n`ID del proveedor`, `Nombre del proveedor`, `Correo electrónico`, `RFC`, `Fecha del movimiento`\n(`YYYY-MM-DD` or `DD/MM/YYYY`), `Tipo de movimiento` (free text such as `Pago semanal` or\n`Servicio`), `Subtotal` (MXN, at least `0.01`). Also accepted: `Provider ID` or `Driver ID` for\nthe id; `Nombre del conductor`, `Razón social` or `Nombre` for the name (the more specific one\nwins when several are present); `Correo` or `Email` for the e-mail.\n"
          },
          "commissions_file": {
            "type": "string",
            "format": "binary",
            "description": "One row per provider per month with the platform commission. Max 5 MB, max 50,000 rows.\nRequired columns: the same provider columns as the movements file (`ID del proveedor`,\n`Nombre del proveedor`, `Correo electrónico`, `RFC`, with the same alternatives), `Mes`\n(`YYYY-MM`) and `Comisión` (MXN). `Comisión Total` and a few legacy export spellings are also\naccepted for the amount.\n"
          }
        }
      },
      "ApiPublicPlatformPayoutRun": {
        "type": "object",
        "description": "A platform payouts run: the files it was planned from, the plan totals, and the stamping progress.\nAmounts are MXN in pesos (not cents). Timestamps are epoch milliseconds.\n",
        "required": [
          "id",
          "status",
          "result",
          "livemode",
          "team",
          "created_at",
          "plan_ready_at",
          "confirmed_at",
          "completed_at",
          "files",
          "months",
          "total_movements",
          "included_count",
          "excluded_count",
          "planned_documents",
          "exclusion_summary",
          "exclusion_code_summary",
          "progress",
          "error"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Run id. Derived from your team, the key's mode and the `Idempotency-Key` you sent, so the\nsame key always names the same run.\n",
            "pattern": "^batchrun_[A-Za-z0-9]{6,40}$",
            "example": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c"
          },
          "status": {
            "$ref": "#/components/schemas/PlatformPayoutRunStatusEnum"
          },
          "result": {
            "$ref": "#/components/schemas/PlatformPayoutRunResultEnum"
          },
          "livemode": {
            "type": "boolean",
            "description": "Mode of the credential that created the run. A test key only ever sees test runs.",
            "example": true
          },
          "team": {
            "type": "string",
            "description": "The master team the run issues from.",
            "example": "team_1234567890"
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "When the run was created (epoch ms).",
            "example": 1788220800000
          },
          "plan_ready_at": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "When planning ended, successfully (`plan_ready`) or not (`plan_failed`). `null` while `planning`.",
            "example": 1788220804120
          },
          "confirmed_at": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "When the run was confirmed for stamping. `null` until then.",
            "example": null
          },
          "completed_at": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "When the worker finished (`completed`) or stopped the run (`failed`). `null` otherwise.",
            "example": null
          },
          "files": {
            "type": "object",
            "description": "Names of the uploaded files, as sent.",
            "required": [
              "movements",
              "commissions"
            ],
            "properties": {
              "movements": {
                "type": "string",
                "example": "movimientos-agosto-2026.csv"
              },
              "commissions": {
                "type": "string",
                "example": "comisiones-agosto-2026.xlsx"
              }
            }
          },
          "months": {
            "type": "array",
            "description": "The `YYYY-MM` months present in the movements file, ascending.",
            "items": {
              "type": "string",
              "example": "2026-08"
            }
          },
          "total_movements": {
            "type": "integer",
            "description": "Rows read from the movements file.",
            "example": 412
          },
          "included_count": {
            "type": "integer",
            "description": "Movements with at least one document to issue.",
            "example": 398
          },
          "excluded_count": {
            "type": "integer",
            "description": "Movements with nothing to issue (see `exclusion_summary`).",
            "example": 14
          },
          "planned_documents": {
            "type": "object",
            "description": "CFDIs the plan will issue, by kind. `income`: one invoice per movement, issued by the\nprovider's team to the master team. `certificate`: one retention certificate\n(Constancia de Retenciones, key 26) per movement, issued by the master team to the provider.\n`commission`: one invoice per provider-month from the commissions file, issued by the\nmaster team to the provider.\n",
            "required": [
              "income",
              "certificate",
              "commission"
            ],
            "properties": {
              "income": {
                "type": "integer",
                "example": 398
              },
              "certificate": {
                "type": "integer",
                "example": 398
              },
              "commission": {
                "type": "integer",
                "example": 57
              }
            }
          },
          "exclusion_summary": {
            "type": "object",
            "description": "Excluded movements, counted by reason, for people. Keys are the Spanish reason sentences\nshown to users (free text that may be reworded); a movement excluded for two reasons has them\njoined with ` · `. Programs should read `exclusion_code_summary` instead.\n",
            "additionalProperties": {
              "type": "integer"
            },
            "example": {
              "Sin sellos (CSD) en Gigstack": 9,
              "El proveedor no tiene cuenta en Gigstack": 5
            }
          },
          "exclusion_code_summary": {
            "type": "object",
            "description": "Excluded movements, counted by exclusion code (see `PlatformPayoutExclusionCode`), for programs. Keys\nare exclusion codes; only codes that occur are present. A movement excluded for two different\nreasons counts once under **each** of its codes, so the values can add up to more than\n`excluded_count`. `{}` on runs planned before codes existed.\n",
            "properties": {
              "invalid_row": {
                "type": "integer"
              },
              "provider_not_found": {
                "type": "integer"
              },
              "missing_tax_id": {
                "type": "integer"
              },
              "missing_legal_name": {
                "type": "integer"
              },
              "missing_zip": {
                "type": "integer"
              },
              "missing_fiscal_data": {
                "type": "integer"
              },
              "csd_expired": {
                "type": "integer"
              },
              "missing_csd": {
                "type": "integer"
              },
              "tax_system_not_allowed": {
                "type": "integer"
              },
              "duplicate_tax_id": {
                "type": "integer"
              },
              "name_mismatch": {
                "type": "integer"
              },
              "missing_series": {
                "type": "integer"
              },
              "public_general_not_allowed": {
                "type": "integer"
              },
              "certificate_month_reserved": {
                "type": "integer"
              },
              "missing_commission": {
                "type": "integer"
              },
              "zero_commission": {
                "type": "integer"
              }
            },
            "additionalProperties": {
              "type": "integer"
            },
            "example": {
              "missing_csd": 9,
              "provider_not_found": 5
            }
          },
          "progress": {
            "type": "object",
            "description": "What the worker has done so far. All zero until the run is confirmed. `stamped_count` and\n`failed_count` count **movements**; the three `*_count` document counters count comprobantes.\n",
            "required": [
              "stamped_count",
              "failed_count",
              "income_invoices_count",
              "certificates_count",
              "commission_invoices_count",
              "commission_failed_count",
              "income_invoices_amount"
            ],
            "properties": {
              "stamped_count": {
                "type": "integer",
                "description": "Movements whose planned documents were all stamped.",
                "example": 0
              },
              "failed_count": {
                "type": "integer",
                "description": "Movements with at least one document that failed for good. Does not include\ncommission invoices (see `commission_failed_count`).\n",
                "example": 0
              },
              "income_invoices_count": {
                "type": "integer",
                "description": "Income invoices stamped.",
                "example": 0
              },
              "certificates_count": {
                "type": "integer",
                "description": "Retention certificates stamped.",
                "example": 0
              },
              "commission_invoices_count": {
                "type": "integer",
                "description": "Commission invoices stamped.",
                "example": 0
              },
              "commission_failed_count": {
                "type": "integer",
                "description": "Commission invoices that failed for good. `0` on runs counted before it existed.",
                "example": 0
              },
              "income_invoices_amount": {
                "type": "number",
                "description": "Sum of the totals of the stamped income invoices, MXN.",
                "example": 0
              }
            }
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Why the plan (`plan_failed`) or the run (`failed`) failed, as a Spanish sentence for end users. `null` otherwise.",
            "example": null
          }
        }
      },
      "ApiPublicPlatformPayoutDocument": {
        "type": "object",
        "description": "The state of one comprobante a movement may produce.",
        "required": [
          "planned",
          "status",
          "reason",
          "reason_code",
          "invoice_id",
          "uuid",
          "total",
          "error",
          "error_code"
        ],
        "properties": {
          "planned": {
            "type": "boolean",
            "description": "Whether the plan issues this document.",
            "example": true
          },
          "status": {
            "type": "string",
            "description": "`planned` - waiting for (or being retried by) the worker. `skipped` - not issued (see `reason`).\n`stamped` - issued. `failed` - given up on (see `error`).\n",
            "enum": [
              "planned",
              "skipped",
              "stamped",
              "failed"
            ],
            "example": "stamped"
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "description": "Why the document is not planned, in Spanish, for people. May be reworded; branch on\n`reason_code`. `null` when it is planned.\n",
            "example": null
          },
          "reason_code": {
            "type": "string",
            "nullable": true,
            "description": "Why the document is not planned, as a stable code (see `PlatformPayoutExclusionCode`). `null` when it is\nplanned, and on documents planned before codes existed.\n",
            "enum": [
              "invalid_row",
              "provider_not_found",
              "missing_tax_id",
              "missing_legal_name",
              "missing_zip",
              "missing_fiscal_data",
              "csd_expired",
              "missing_csd",
              "tax_system_not_allowed",
              "duplicate_tax_id",
              "name_mismatch",
              "missing_series",
              "public_general_not_allowed",
              "certificate_month_reserved",
              "missing_commission",
              "zero_commission",
              null
            ],
            "example": null
          },
          "invoice_id": {
            "type": "string",
            "nullable": true,
            "description": "Id of the stamped document. For `income` it is an invoice of the **provider's** team\n(`provider.team`); for `certificate` it is a retention of the master team (its UUID).\n",
            "example": "7C2E4B1A-9D3F-4E8A-B6C5-1F2A3B4C5D6E"
          },
          "uuid": {
            "type": "string",
            "nullable": true,
            "description": "SAT folio fiscal (UUID) of the stamped document.",
            "example": "7C2E4B1A-9D3F-4E8A-B6C5-1F2A3B4C5D6E"
          },
          "total": {
            "type": "number",
            "nullable": true,
            "description": "Total of the stamped income invoice, MXN. Not set for certificates.",
            "example": 1323.75
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Last stamping error, in Spanish. Can be set while `status` is still `planned` (a transient\nfailure that will be retried).\n",
            "example": null
          },
          "error_code": {
            "type": "string",
            "nullable": true,
            "description": "The stamping or PAC error code behind `error`: `interrupted_stamp` (sent to the PAC but never\nrecorded; not retried), `NETWORK_ERROR` or `HTTP_<status>` (e.g. `HTTP_503`, transient),\n`team_out_of_scope` (the provider's team is no longer one this run may issue for), or a CFDI\nerror code such as `STAMPING_ERROR` or `PAC_UNAVAILABLE`. `null` when there is no error.\n",
            "example": null
          }
        }
      },
      "ApiPublicPlatformPayoutMovement": {
        "type": "object",
        "description": "One row of the movements file and the documents it produces.",
        "required": [
          "id",
          "line",
          "status",
          "provider",
          "movement_type",
          "date",
          "month",
          "subtotal",
          "commission",
          "exclusion_reason",
          "exclusion_codes",
          "error",
          "income",
          "certificate"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Movement id, unique within the run and stable across re-uploads of the same row. Treat it as opaque.",
            "example": "P10482_2026-08-04_125000_0"
          },
          "line": {
            "type": "integer",
            "description": "Row number in the movements file, counting the header as line 1.",
            "example": 2
          },
          "status": {
            "type": "string",
            "description": "`planned` - has documents still to issue. `excluded` - nothing to issue (see `exclusion_reason`).\n`stamped` - every planned document was issued. `failed` - at least one planned document failed.\n",
            "enum": [
              "planned",
              "excluded",
              "stamped",
              "failed"
            ],
            "example": "stamped"
          },
          "provider": {
            "type": "object",
            "description": "The provider (for example a driver, courier, host or seller) the payout goes to.",
            "required": [
              "id",
              "name",
              "email",
              "tax_id",
              "team"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "`ID del proveedor` from the file (or its alternative `Provider ID` / `Driver ID`).",
                "example": "P10482"
              },
              "name": {
                "type": "string",
                "description": "Legal name of the matched gigstack team, or the file's name when no team matched.",
                "example": "ESCUELA KEMPER URGATE"
              },
              "email": {
                "type": "string",
                "description": "E-mail from the file, lowercased.",
                "example": "proveedor@example.com"
              },
              "tax_id": {
                "type": "string",
                "description": "RFC of the matched gigstack team, or the file's RFC when no team matched.",
                "example": "EKU9003173C9"
              },
              "team": {
                "type": "string",
                "nullable": true,
                "description": "The provider's gigstack team in your billing account, matched by `ID del proveedor`\n(team `metadata.driverId`), then RFC, then e-mail. `null` when no team matched.\n",
                "example": "team_0987654321"
              }
            }
          },
          "movement_type": {
            "type": "string",
            "description": "`Tipo de movimiento` from the file.",
            "example": "Pago semanal"
          },
          "date": {
            "type": "string",
            "description": "Movement date, `YYYY-MM-DD`. Empty when the file's date could not be read.",
            "example": "2026-08-04"
          },
          "month": {
            "type": "string",
            "description": "`YYYY-MM` of `date`.",
            "example": "2026-08"
          },
          "subtotal": {
            "type": "number",
            "description": "Subtotal from the file, rounded to the cent for display (MXN).",
            "example": 1250
          },
          "commission": {
            "type": "number",
            "description": "This movement's share of the provider's monthly commission, prorated by subtotal across the provider's movements of the month (MXN).",
            "example": 96.15
          },
          "exclusion_reason": {
            "type": "string",
            "nullable": true,
            "description": "Why nothing is issued for this movement, in Spanish, for people (two reasons are joined with\n` · `). `null` unless `status` is `excluded`. Branch on `exclusion_codes` instead.\n",
            "example": null
          },
          "exclusion_codes": {
            "type": "array",
            "description": "The distinct codes behind `exclusion_reason`, one per distinct reason (at most one for the\nincome invoice and one for the certificate). Empty when the movement is not excluded, and on\nmovements planned before codes existed.\n",
            "items": {
              "$ref": "#/components/schemas/PlatformPayoutExclusionCode"
            },
            "example": []
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Last stamping error on this movement, in Spanish.",
            "example": null
          },
          "income": {
            "$ref": "#/components/schemas/ApiPublicPlatformPayoutDocument"
          },
          "certificate": {
            "$ref": "#/components/schemas/ApiPublicPlatformPayoutDocument"
          }
        }
      },
      "ApiPublicPlatformPayoutMovementsPage": {
        "type": "object",
        "required": [
          "data",
          "next",
          "has_more"
        ],
        "properties": {
          "data": {
            "type": "array",
            "description": "Movements in file order (ascending `line`).",
            "items": {
              "$ref": "#/components/schemas/ApiPublicPlatformPayoutMovement"
            }
          },
          "next": {
            "type": "string",
            "nullable": true,
            "description": "Opaque cursor; send it back as `next` to get the following page. `null` on the last page.",
            "example": "51"
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows.",
            "example": true
          }
        }
      },
      "ApiPublicPlatformPayoutRunConfirmation": {
        "type": "object",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c"
          },
          "status": {
            "type": "string",
            "description": "`stamping` after a successful confirm; a repeated confirm returns the current status (`stamping` or `completed`).",
            "enum": [
              "stamping",
              "completed"
            ],
            "example": "stamping"
          }
        }
      },
      "InvoiceBatchCreateInput": {
        "type": "object",
        "description": "Up to 1,000 income invoices. Each item is **exactly** the body of `POST /invoices/income`, and must carry\nits own `idempotency_key`, unique within the batch.\n\nItems are validated one by one: an invalid item is listed in the batch's `rejected` and the others go\nahead. Only a body without a non-empty `invoices` array (`invalid_body`) or with more than 1,000 items\n(`too_many_items`) refuses the whole request.\n\n`livemode`, `team` and `owner` in an item are ignored (they come from the credential), and so is\n`return_files`: a batch does not return files. Keep the whole JSON body under 10 MB.\n",
        "required": [
          "invoices"
        ],
        "properties": {
          "invoices": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1000,
            "description": "The invoices, in the order you want them reported. An item's `index` is its position here (from 0).",
            "items": {
              "$ref": "#/components/schemas/InvoiceBatchItemInput"
            }
          }
        }
      },
      "InvoiceBatchItemInput": {
        "description": "One invoice of a batch. The body of `POST /invoices/income`, with `idempotency_key` required.",
        "allOf": [
          {
            "$ref": "#/components/schemas/InvoiceIncomeInput"
          },
          {
            "type": "object",
            "required": [
              "idempotency_key"
            ],
            "properties": {
              "idempotency_key": {
                "type": "string",
                "minLength": 1,
                "maxLength": 256,
                "description": "Your identifier for this invoice (for example your order id), unique within the batch.\nSurrounding spaces are trimmed. It is the same key as on `POST /invoices/income`, so an\ninvoice already issued under it, by an earlier batch or a single call, is not issued\nagain: the item ends `duplicate`.\n",
                "example": "order-2026-09-000123"
              }
            }
          }
        ]
      },
      "InvoiceBatchStatusEnum": {
        "type": "string",
        "description": "- `processing`: some accepted items are still queued.\n- `completed`: every accepted item has a final status. Read `result` to know how it went.\n",
        "enum": [
          "processing",
          "completed"
        ],
        "example": "processing"
      },
      "InvoiceBatchResultEnum": {
        "type": "string",
        "nullable": true,
        "description": "How a finished batch turned out. `null` while `status` is `processing`.\n\n- `completed`: every item was issued (`stamped`, or `duplicate` because it had been issued before), and\n  nothing was rejected.\n- `partially_completed`: at least one item was issued, and at least one was not (`failed`,\n  `needs_review` or rejected up front).\n- `failed`: no item was issued.\n",
        "enum": [
          "completed",
          "partially_completed",
          "failed",
          null
        ],
        "example": "partially_completed"
      },
      "InvoiceBatchCounts": {
        "type": "object",
        "description": "Accepted items by status. `queued` is what is still in flight, so it reaches `0` when the batch completes.\nThe five counts add up to `accepted`; rejected items are not counted here.\n",
        "required": [
          "queued",
          "stamped",
          "failed",
          "duplicate",
          "needs_review"
        ],
        "properties": {
          "queued": {
            "type": "integer",
            "description": "Waiting for, or in, a stamping attempt.",
            "example": 0
          },
          "stamped": {
            "type": "integer",
            "description": "Stamped by this batch.",
            "example": 245
          },
          "failed": {
            "type": "integer",
            "description": "Ended without an invoice. See each item's `error`.",
            "example": 2
          },
          "duplicate": {
            "type": "integer",
            "description": "Already issued under the same `idempotency_key` before; not issued again.",
            "example": 1
          },
          "needs_review": {
            "type": "integer",
            "description": "The PAC could not confirm whether the invoice was stamped. gigstack support resolves these.",
            "example": 0
          }
        }
      },
      "InvoiceBatchError": {
        "type": "object",
        "description": "Why an item was rejected or did not produce an invoice.",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable reason. See the operation descriptions for the possible values.",
            "example": "CFDI40147"
          },
          "message": {
            "type": "string",
            "description": "Human-readable reason, at most 500 characters. Stamping errors are in Spanish, as on `POST /invoices/income`.",
            "example": "Error al timbrar la factura: El campo UsoCFDI no es válido"
          }
        }
      },
      "InvoiceBatchRejectedItem": {
        "type": "object",
        "description": "An item refused by validation when the batch was created. Nothing was stamped or charged for it.",
        "required": [
          "index",
          "idempotency_key",
          "error"
        ],
        "properties": {
          "index": {
            "type": "integer",
            "description": "Position of the item in `invoices` (from 0).",
            "example": 17
          },
          "idempotency_key": {
            "type": "string",
            "nullable": true,
            "description": "The item's key, trimmed. `null` when the item was not an object or had no key.",
            "example": "order-2026-09-000140"
          },
          "error": {
            "allOf": [
              {
                "$ref": "#/components/schemas/InvoiceBatchError"
              }
            ],
            "description": "`code` is one of:\n\n- `invalid_item`: the item is not a JSON object.\n- `idempotency_key_required`: no `idempotency_key`, or an empty one.\n- `invalid_idempotency_key`: the key is longer than 256 characters.\n- `duplicate_idempotency_key`: an earlier item of this batch has the same key (the message names its index).\n- `invalid_body`: the item fails the `POST /invoices/income` body validation; the message lists\n  each `path: message`.\n"
          }
        }
      },
      "ApiPublicInvoiceBatch": {
        "type": "object",
        "description": "An income invoice batch: how many invoices it received, which were rejected up front, and the progress of\nthe rest. Timestamps are epoch milliseconds.\n",
        "required": [
          "id",
          "object",
          "type",
          "livemode",
          "status",
          "result",
          "total",
          "accepted",
          "rejected",
          "counts",
          "created_at",
          "completed_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Batch id. Derived from your team, the credential's mode and the `Idempotency-Key` you sent, so the\nsame key always names the same batch.\n",
            "pattern": "^ibatch_[0-9a-f]{32}$",
            "example": "ibatch_5d41402abc4b2a76b9719d911017c592"
          },
          "object": {
            "type": "string",
            "enum": [
              "invoice_batch"
            ],
            "example": "invoice_batch"
          },
          "type": {
            "type": "string",
            "description": "Kind of document the batch issues. Only `income` exists.",
            "enum": [
              "income"
            ],
            "example": "income"
          },
          "livemode": {
            "type": "boolean",
            "description": "Mode of the credential that created the batch. A test key only ever sees test batches.",
            "example": true
          },
          "status": {
            "$ref": "#/components/schemas/InvoiceBatchStatusEnum"
          },
          "result": {
            "$ref": "#/components/schemas/InvoiceBatchResultEnum"
          },
          "total": {
            "type": "integer",
            "description": "Invoices in the request.",
            "example": 250
          },
          "accepted": {
            "type": "integer",
            "description": "Invoices that passed validation and are processed.",
            "example": 248
          },
          "rejected": {
            "type": "array",
            "description": "Invoices refused by validation, in request order. Empty when every item was accepted.",
            "items": {
              "$ref": "#/components/schemas/InvoiceBatchRejectedItem"
            }
          },
          "counts": {
            "$ref": "#/components/schemas/InvoiceBatchCounts"
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "When the batch was created (epoch ms).",
            "example": 1790780400000
          },
          "completed_at": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "When the last item reached a final status (epoch ms). `null` while `processing`.",
            "example": 1790784000000
          }
        }
      },
      "InvoiceBatchItemStatusEnum": {
        "type": "string",
        "description": "- `queued`: waiting for, or in, a stamping attempt. An attempt that failed for a temporary reason (PAC\n  unavailable, its answer lost) keeps the item `queued` and is retried, up to 6 attempts.\n- `stamped`: the invoice was issued by this batch. `uuid` and `invoice_id` are set.\n- `failed`: no invoice was issued. `error` says why.\n- `duplicate`: an invoice already existed under this `idempotency_key` (an earlier batch, a single\n  `POST /invoices/income`, or a redelivery of this item). `uuid` names it; nothing was issued or charged again.\n- `needs_review`: the PAC could not confirm whether the invoice was stamped. It is never retried\n  automatically, so it cannot be issued twice; contact support with the batch id and `index`.\n",
        "enum": [
          "queued",
          "stamped",
          "failed",
          "duplicate",
          "needs_review"
        ],
        "example": "stamped"
      },
      "ApiPublicInvoiceBatchItem": {
        "type": "object",
        "description": "One accepted invoice of a batch. Rejected items are not listed here; they are in the batch's `rejected`.",
        "required": [
          "index",
          "idempotency_key",
          "status",
          "invoice_id",
          "uuid",
          "error",
          "attempts"
        ],
        "properties": {
          "index": {
            "type": "integer",
            "description": "Position of the item in the request's `invoices` (from 0).",
            "example": 0
          },
          "idempotency_key": {
            "type": "string",
            "description": "The item's `idempotency_key`, trimmed.",
            "example": "order-2026-09-000123"
          },
          "status": {
            "$ref": "#/components/schemas/InvoiceBatchItemStatusEnum"
          },
          "invoice_id": {
            "type": "string",
            "nullable": true,
            "description": "Id of the invoice, for `GET /invoices/income/{id}`. Set for `stamped` and `duplicate`.",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          },
          "uuid": {
            "type": "string",
            "nullable": true,
            "description": "Folio fiscal (UUID) of the CFDI. Set for `stamped` and `duplicate`.",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          },
          "error": {
            "anyOf": [
              {
                "description": "Why the item has no invoice. Set only for `failed` and `needs_review`; `null` otherwise, including\nwhile a `queued` item waits to retry. `code` is either what `POST /invoices/income` would have\nanswered for the same body (a SAT/PAC code such as `CFDI40147`, `SAT_NOT_CONNECTED`,\n`CSD_VALIDATION_ERROR`, `PAC_UNAVAILABLE`, `PAC_OUTCOME_UNKNOWN`, `STAMP_NEEDS_REVIEW`, …), or one\nof the batch's own:\n\n- `credential_revoked`: the API key that created the batch was revoked or disabled before this\n  item ran. Remaining items fail the same way.\n- `credit_limit_reached`: the team's credit limit was reached.\n- `http_<status>`: the invoice endpoint answered that status without a code (for example\n  `http_404` for a client or service id that does not exist).\n- `auth_unavailable`, `internal_error`, `idempotency_in_progress`: a temporary failure that\n  persisted through every attempt.\n",
                "allOf": [
                  {
                    "$ref": "#/components/schemas/InvoiceBatchError"
                  }
                ]
              },
              {
                "type": "object",
                "nullable": true,
                "enum": [
                  null
                ]
              }
            ]
          },
          "attempts": {
            "type": "integer",
            "description": "Stamping attempts made for this item so far.",
            "example": 1
          }
        }
      },
      "ApiPublicInvoiceBatchItemsPage": {
        "type": "object",
        "required": [
          "data",
          "next",
          "has_more"
        ],
        "properties": {
          "data": {
            "type": "array",
            "description": "Items in request order (ascending `index`).",
            "items": {
              "$ref": "#/components/schemas/ApiPublicInvoiceBatchItem"
            }
          },
          "next": {
            "type": "string",
            "nullable": true,
            "description": "Cursor; send it back as `next` to get the following page. `null` on the last page.",
            "example": "99"
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page follows.",
            "example": true
          }
        }
      },
      "IdempotencyInProgressResponse": {
        "type": "object",
        "description": "Raw `409` body of `POST /invoices/income` when another request with the same `idempotency_key` is being\nprocessed. Not the standardized envelope. Retry later with the same key.\n",
        "required": [
          "message",
          "error",
          "retryable"
        ],
        "properties": {
          "message": {
            "type": "string",
            "example": "An invoice with this idempotency_key is already being created"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "idempotency_in_progress"
                ],
                "example": "idempotency_in_progress"
              },
              "message": {
                "type": "string",
                "example": "An invoice with this idempotency_key is already being created; retry later"
              }
            }
          },
          "retryable": {
            "type": "boolean",
            "enum": [
              true
            ],
            "example": true
          }
        }
      },
      "EmbeddedClientInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "nullable": true
          },
          "search": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "on_key",
              "on_value"
            ],
            "properties": {
              "on_key": {
                "type": "string"
              },
              "on_value": {
                "type": "string"
              },
              "auto_create": {
                "type": "boolean",
                "nullable": true
              },
              "safety_check": {
                "type": "boolean",
                "nullable": true
              },
              "update": {
                "type": "boolean",
                "nullable": true
              }
            },
            "nullable": true
          },
          "address": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "country": {
                "type": "string",
                "nullable": true,
                "maxLength": 3
              },
              "street": {
                "type": "string",
                "nullable": true
              },
              "zip": {
                "type": "string",
                "nullable": true
              },
              "city": {
                "type": "string",
                "nullable": true
              },
              "state": {
                "type": "string",
                "nullable": true
              },
              "exterior": {
                "type": "string",
                "nullable": true
              },
              "interior": {
                "type": "string",
                "nullable": true
              },
              "municipality": {
                "type": "string",
                "nullable": true
              },
              "neighborhood": {
                "type": "string",
                "nullable": true
              }
            },
            "nullable": true
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "company": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "bcc": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "properties": {}
          },
          "legal_name": {
            "type": "string",
            "nullable": true
          },
          "tax_id": {
            "type": "string",
            "nullable": true
          },
          "use": {
            "type": "string",
            "nullable": true
          },
          "tax_system": {
            "type": "string",
            "nullable": true
          },
          "document_type": {
            "description": "DIAN identification document code",
            "type": "string",
            "enum": [
              "",
              "11",
              "12",
              "13",
              "21",
              "22",
              "31",
              "41",
              "42",
              "47",
              "48",
              "50",
              "91",
              null
            ],
            "nullable": true
          },
          "organization_type": {
            "description": "1 = persona jurídica, 2 = persona natural",
            "oneOf": [
              {
                "type": "string",
                "enum": [
                  "",
                  "1",
                  "2",
                  null
                ],
                "nullable": true
              },
              {
                "type": "number",
                "enum": [
                  1,
                  2
                ]
              }
            ]
          },
          "tribute_code": {
            "description": "'01' = responsable de IVA, 'ZZ' = no aplica",
            "type": "string",
            "enum": [
              "",
              "01",
              "ZZ",
              null
            ],
            "nullable": true
          },
          "fiscal_responsibilities": {
            "description": "DIAN responsabilidades fiscales (lista 53). Omitted means 'R-99-PN' (no responsable)",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "O-13",
                "O-15",
                "O-23",
                "O-47",
                "R-99-PN"
              ]
            },
            "nullable": true
          },
          "dv": {
            "description": "NIT verification digit",
            "type": "string",
            "nullable": true,
            "pattern": "^[0-9]?$"
          },
          "municipality_code": {
            "description": "DANE municipality code, only for clients domiciled in Colombia",
            "type": "string",
            "nullable": true,
            "pattern": "^([0-9]{5})?$"
          }
        }
      },
      "ClientUpdateInput": {
        "description": "Update body for `PUT /v2/clients/{id}`. An omitted `name` is preserved from the\nexisting client before validation. Send only the profile fields you intend\nto change; creation uses the separate `ClientInput` schema.\n\nUnknown top-level keys are rejected (`400 validation_failed` / `unexpected_key`);\n`metadata` is the one object that accepts arbitrary keys. `team`, `livemode` and\n`owner` are reserved and injected by the auth middleware.\n\nThe `document_type`, `organization_type`, `tribute_code`, `fiscal_responsibilities`,\n`dv` and `municipality_code`\nfields are the Colombian DIAN identification set. They are accepted for every team\nregardless of country; each also accepts the empty string, which means \"not set\" and is\ndropped before the client is stored.\n",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "search": {
            "description": "Search for an existing client before creating. If a match is found, the existing client is returned (or updated if `update: true`).\nThis enables upsert-like behavior to avoid duplicate clients.\n",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "on_key",
              "on_value"
            ],
            "properties": {
              "on_key": {
                "description": "The field to search on (e.g., 'tax_id', 'email', 'name')",
                "example": "tax_id",
                "type": "string"
              },
              "on_value": {
                "description": "The value to match against the specified field",
                "example": "PEGJ800101ABC",
                "type": "string"
              },
              "auto_create": {
                "type": "boolean",
                "nullable": true
              },
              "safety_check": {
                "type": "boolean",
                "nullable": true
              },
              "update": {
                "description": "If true and a match is found, update the existing client with the provided data. If false, return the existing client without modifications.",
                "example": false,
                "type": "boolean",
                "nullable": true
              }
            },
            "nullable": true
          },
          "address": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "country": {
                "example": "MEX",
                "type": "string",
                "nullable": true,
                "maxLength": 3
              },
              "street": {
                "example": "Av. Insurgentes Sur",
                "type": "string",
                "nullable": true
              },
              "zip": {
                "example": "03100",
                "type": "string",
                "nullable": true
              },
              "city": {
                "example": "Ciudad de México",
                "type": "string",
                "nullable": true
              },
              "state": {
                "example": "CDMX",
                "type": "string",
                "nullable": true
              },
              "exterior": {
                "example": "123",
                "type": "string",
                "nullable": true
              },
              "interior": {
                "example": "4B",
                "type": "string",
                "nullable": true
              },
              "municipality": {
                "example": "Benito Juárez",
                "type": "string",
                "nullable": true
              },
              "neighborhood": {
                "example": "Del Valle",
                "type": "string",
                "nullable": true
              }
            },
            "nullable": true
          },
          "name": {
            "example": "Juan Pérez García",
            "type": "string"
          },
          "company": {
            "example": "Empresa SA de CV",
            "type": "string",
            "nullable": true
          },
          "phone": {
            "example": "+52 55 1234 5678",
            "type": "string",
            "nullable": true
          },
          "email": {
            "example": "juan.perez@ejemplo.com",
            "type": "string",
            "nullable": true,
            "format": "email"
          },
          "bcc": {
            "example": [
              "admin@empresa.com"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "metadata": {
            "example": {
              "custom_field": "value"
            },
            "type": "object",
            "additionalProperties": true,
            "properties": {}
          },
          "legal_name": {
            "example": "Juan Pérez García",
            "type": "string",
            "nullable": true
          },
          "tax_id": {
            "example": "PEGJ800101ABC",
            "type": "string",
            "nullable": true
          },
          "use": {
            "example": "G03",
            "type": "string",
            "nullable": true
          },
          "tax_system": {
            "example": "601",
            "type": "string",
            "nullable": true
          },
          "defaults": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "keep_full_legal_name": {
                "example": false,
                "type": "boolean"
              },
              "issue_automatic_invoices": {
                "example": false,
                "type": "boolean"
              },
              "issue_invoiceable_receipts": {
                "example": true,
                "type": "boolean"
              }
            }
          },
          "document_type": {
            "description": "**Colombia (DIAN).** Identification document code.\n`11` registro civil, `12` tarjeta de identidad, `13` cédula de ciudadanía,\n`21` tarjeta de extranjería, `22` cédula de extranjería, `31` NIT,\n`41` pasaporte, `42` documento de identificación extranjero,\n`47` PEP, `48` PPT, `50` NIT de otro país, `91` NUIP.\nThe empty string means \"not set\" and is dropped before the client is stored.\n",
            "example": "31",
            "type": "string",
            "enum": [
              "",
              "11",
              "12",
              "13",
              "21",
              "22",
              "31",
              "41",
              "42",
              "47",
              "48",
              "50",
              "91",
              null
            ],
            "nullable": true
          },
          "organization_type": {
            "description": "**Colombia (DIAN).** `1` = persona jurídica, `2` = persona natural.\nAccepted as either a number (`1`, `2`) or a string (`\"1\"`, `\"2\"`).\nThe empty string means \"not set\".\n",
            "example": "2",
            "oneOf": [
              {
                "type": "string",
                "enum": [
                  "",
                  "1",
                  "2",
                  null
                ],
                "nullable": true
              },
              {
                "type": "number",
                "enum": [
                  1,
                  2
                ]
              }
            ]
          },
          "tribute_code": {
            "description": "**Colombia (DIAN).** `01` = responsable de IVA, `ZZ` = no aplica.\nThe empty string means \"not set\".\n",
            "example": "01",
            "type": "string",
            "enum": [
              "",
              "01",
              "ZZ",
              null
            ],
            "nullable": true
          },
          "fiscal_responsibilities": {
            "description": "**Colombia (DIAN).** Responsabilidades fiscales del cliente (lista 53).\n`O-13` gran contribuyente, `O-15` autorretenedor,\n`O-23` agente de retención de IVA, `O-47` régimen simple de tributación,\n`R-99-PN` no responsable.\nOmit the field (or send an empty array) to leave it unset — the client is\nthen reported as `R-99-PN`, which is also the value that applies when the\narray carries only that code. `R-99-PN` excludes every `O-*` code: if both\nare sent, only the `O-*` ones are reported.\n",
            "example": [
              "O-15",
              "O-23"
            ],
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "O-13",
                "O-15",
                "O-23",
                "O-47",
                "R-99-PN"
              ]
            },
            "nullable": true
          },
          "dv": {
            "description": "**Colombia (DIAN).** NIT verification digit — a single digit, or the empty\nstring for \"not set\".\n",
            "example": "7",
            "type": "string",
            "nullable": true,
            "pattern": "^[0-9]?$"
          },
          "municipality_code": {
            "description": "**Colombia (DIAN).** DANE municipality code — exactly five digits, or the empty\nstring for \"not set\". Only meaningful for clients domiciled in Colombia.\n",
            "example": "05001",
            "type": "string",
            "nullable": true,
            "pattern": "^([0-9]{5})?$"
          },
          "check_pending_receipts": {
            "description": "Only applies to `PUT /clients/{id}`. When `true` (default) and the updated client passes fiscal validation, all of the client's pending receipts are automatically invoiced using the new client data. Set to `false` to skip this behavior.\n",
            "example": true,
            "default": true,
            "type": "boolean"
          }
        }
      }
    }
  },
  "paths": {
    "/clients": {
      "get": {
        "operationId": "listClients",
        "tags": [
          "Clients"
        ],
        "summary": "List clients",
        "description": "Retrieve a paginated list of clients with powerful filtering capabilities.\n\n**gigstack Connect:** Access other teams' clients using the `team` parameter.\n\n**Filtering Options:**\n- Filter by creation date using comparison operators\n- Filter by metadata fields using dot or underscore notation (e.g., `metadata.external_id` or `metadata_external_id`)\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGtParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLtParam"
          },
          {
            "$ref": "#/components/parameters/TaxIdFilterParam"
          },
          {
            "name": "metadata.{key}",
            "in": "query",
            "description": "Filter by any metadata field using dot notation (e.g., `metadata.external_id=EXT-123`)\nor underscore notation (e.g., `metadata_external_id=EXT-123`).\nBoth formats are supported and equivalent.\nUses Typesense search for efficient querying without requiring Firestore indexes.\n",
            "required": false,
            "schema": {
              "type": "string"
            },
            "style": "form"
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination when using metadata filters (default 1).\nOnly applies when filtering by metadata fields.\n",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Clients retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Clients retrieved successfully"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiPublicClient"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "example": false
                    },
                    "total_results": {
                      "type": "integer",
                      "example": 25
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "example": "eyJjcmVhdGVkX2F0IjoxNjc3NjUxMjM0fQ=="
                    }
                  }
                },
                "example": {
                  "message": "Clients retrieved successfully",
                  "data": [
                    {
                      "id": "client_1234567890",
                      "name": "Juan Pérez García",
                      "email": "juan.perez@ejemplo.com",
                      "tax_id": "PEGJ800101ABC",
                      "tax_system": "601",
                      "legal_name": "Juan Pérez García",
                      "address": {
                        "street": "Av. Insurgentes Sur 123",
                        "zip": "03100",
                        "city": "Ciudad de México",
                        "state": "CDMX",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "livemode": true,
                      "created_at": 1677651234,
                      "team": "team_1234567890",
                      "owner": "user_1234567890",
                      "from": "api"
                    }
                  ],
                  "has_more": false,
                  "total_results": 1
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createClients",
        "tags": [
          "Clients"
        ],
        "summary": "Create client",
        "description": "[Small working example](/recipes/customer)\n\n**Integration note:** Creating a contact does not establish fiscal validity. Inspect fiscal_validation when returned; contact-only input can produce status skipped. A matching search with update false returns the existing customer with HTTP 200; a new record returns 201. Read [shared fields](/concepts/shared-fields) and the [Mexico](/countries/mexico) or [Colombia](/countries/colombia) guide for country-specific meaning. The linked fiscal recipes and staging issuance results use a Mexican issuer.\n\nCreate a new client with fiscal information for Mexican tax compliance.\n\n**Duplicate Prevention (Upsert):** Use the `search` parameter to find existing clients before creating:\n- If a match is found and `search.update` is `false` (default): Returns the existing client without modifications.\n- If a match is found and `search.update` is `true`: Updates the existing client with the provided data and returns it.\n- If no match is found: Creates a new client.\n\nThis is useful for integrations that may send the same client multiple times.\n\n**gigstack Connect:** Create clients for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientInput"
              },
              "example": {
                "name": "Juan Pérez García",
                "email": "juan.perez@ejemplo.com",
                "company": "Empresa SA de CV",
                "phone": "+52 55 1234 5678",
                "legal_name": "Juan Pérez García",
                "tax_id": "PEGJ800101ABC",
                "use": "G03",
                "tax_system": "601",
                "address": {
                  "country": "MEX",
                  "street": "Av. Insurgentes Sur",
                  "zip": "03100",
                  "city": "Ciudad de México",
                  "state": "CDMX",
                  "exterior": "123",
                  "interior": "4B",
                  "municipality": "Benito Juárez",
                  "neighborhood": "Del Valle"
                },
                "bcc": [
                  "admin@empresa.com"
                ],
                "metadata": {
                  "custom_field": "value",
                  "department": "sales"
                },
                "defaults": {
                  "keep_full_legal_name": false,
                  "issue_automatic_invoices": false,
                  "issue_invoiceable_receipts": true
                },
                "search": {
                  "on_key": "tax_id",
                  "on_value": "PEGJ800101ABC",
                  "update": false
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing client found (when using `search` parameter)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Existing client found"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicClient"
                    }
                  }
                },
                "examples": {
                  "existingClient": {
                    "summary": "Existing client found",
                    "value": {
                      "message": "Existing client found",
                      "data": {
                        "id": "client_1234567890",
                        "name": "Juan Pérez García",
                        "email": "juan.perez@ejemplo.com",
                        "tax_id": "PEGJ800101ABC",
                        "tax_system": "601",
                        "legal_name": "Juan Pérez García",
                        "address": {
                          "street": "Av. Insurgentes Sur 123",
                          "zip": "03100",
                          "city": "Ciudad de México",
                          "state": "CDMX",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "livemode": true,
                        "created_at": 1677651234,
                        "team": "team_1234567890",
                        "owner": "user_1234567890",
                        "from": "api"
                      }
                    }
                  },
                  "existingClientUpdated": {
                    "summary": "Existing client found and updated",
                    "value": {
                      "message": "Existing client found and updated",
                      "data": {
                        "id": "client_1234567890",
                        "name": "Juan Pérez García",
                        "email": "juan.perez@ejemplo.com",
                        "tax_id": "PEGJ800101ABC",
                        "tax_system": "601",
                        "legal_name": "Juan Pérez García",
                        "address": {
                          "street": "Av. Insurgentes Sur 123",
                          "zip": "03100",
                          "city": "Ciudad de México",
                          "state": "CDMX",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "livemode": true,
                        "created_at": 1677651234,
                        "team": "team_1234567890",
                        "owner": "user_1234567890",
                        "from": "api"
                      }
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Client created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Client created successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicClient"
                    }
                  }
                },
                "example": {
                  "message": "Client created successfully",
                  "data": {
                    "id": "client_1234567890",
                    "name": "Juan Pérez García",
                    "email": "juan.perez@ejemplo.com",
                    "tax_id": "PEGJ800101ABC",
                    "tax_system": "601",
                    "legal_name": "Juan Pérez García",
                    "address": {
                      "street": "Av. Insurgentes Sur 123",
                      "zip": "03100",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "country": "MEX"
                    },
                    "is_valid": true,
                    "livemode": true,
                    "created_at": 1677651234,
                    "team": "team_1234567890",
                    "owner": "user_1234567890",
                    "from": "api",
                    "efos": {
                      "is_valid": true
                    },
                    "fiscal_validation": {
                      "status": "valid"
                    },
                    "sat_status": {
                      "is_risky": false,
                      "efos": {
                        "is_valid": true
                      },
                      "hits": [],
                      "checked_at": 1776887458784
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict - Multiple clients match the search criteria",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "resource_conflict"
                        },
                        "message": {
                          "type": "string",
                          "example": "Multiple clients found matching tax_id=\"PEGJ800101ABC\". Please use a more specific search criteria."
                        },
                        "details": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "List of matching client IDs",
                          "example": [
                            "client_1234567890",
                            "client_0987654321"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/clients/{id}": {
      "get": {
        "operationId": "getClientsById",
        "tags": [
          "Clients"
        ],
        "summary": "Get client",
        "description": "Retrieve a specific client by ID.\n\n**gigstack Connect:** Access other teams' clients using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "client_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Client retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Client retrieved successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicClient"
                    }
                  }
                },
                "example": {
                  "message": "Client retrieved successfully",
                  "data": {
                    "id": "client_1234567890",
                    "name": "Juan Pérez García",
                    "email": "juan.perez@ejemplo.com",
                    "tax_id": "PEGJ800101ABC",
                    "tax_system": "601",
                    "legal_name": "Juan Pérez García",
                    "address": {
                      "street": "Av. Insurgentes Sur 123",
                      "zip": "03100",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "country": "MEX"
                    },
                    "is_valid": true,
                    "livemode": true,
                    "created_at": 1677651234,
                    "team": "team_1234567890",
                    "owner": "user_1234567890",
                    "from": "api"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "put": {
        "operationId": "updateClientsById",
        "tags": [
          "Clients"
        ],
        "summary": "Update client",
        "description": "Update an existing client.\n\n**Pending receipts:** By default, after a successful update, if the client passes fiscal validation, all of the client's pending receipts are automatically invoiced using the new client data. Set `check_pending_receipts: false` in the body to skip this behavior. When the check runs, the response includes a `pending_receipts` summary.\n\n**gigstack Connect:** Update other teams' clients using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "client_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientUpdateInput"
              },
              "example": {
                "name": "Juan Pérez García",
                "email": "juan.perez.updated@ejemplo.com",
                "company": "Empresa SA de CV - Sucursal Norte",
                "phone": "+52 55 1234 5678",
                "legal_name": "Juan Pérez García",
                "tax_id": "PEGJ800101ABC",
                "use": "G03",
                "tax_system": "601",
                "address": {
                  "country": "MEX",
                  "street": "Av. Insurgentes Sur",
                  "zip": "03100",
                  "city": "Ciudad de México",
                  "state": "CDMX",
                  "exterior": "123",
                  "interior": "4B",
                  "municipality": "Benito Juárez",
                  "neighborhood": "Del Valle"
                },
                "bcc": [
                  "admin@empresa.com",
                  "contabilidad@empresa.com"
                ],
                "metadata": {
                  "updated_reason": "Address change",
                  "priority_client": true
                },
                "defaults": {
                  "keep_full_legal_name": true,
                  "issue_automatic_invoices": true,
                  "issue_invoiceable_receipts": true
                },
                "check_pending_receipts": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Client updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Client updated successfully"
                    },
                    "data": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/ApiPublicClient"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "pending_receipts": {
                              "$ref": "#/components/schemas/PendingReceiptsSummary"
                            }
                          }
                        }
                      ]
                    }
                  }
                },
                "example": {
                  "message": "Client updated successfully",
                  "data": {
                    "id": "client_1234567890",
                    "name": "Juan Pérez García",
                    "email": "juan.perez@ejemplo.com",
                    "tax_id": "PEGJ800101ABC",
                    "tax_system": "601",
                    "legal_name": "Juan Pérez García",
                    "address": {
                      "street": "Av. Insurgentes Sur 123",
                      "zip": "03100",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "country": "MEX"
                    },
                    "is_valid": true,
                    "livemode": true,
                    "created_at": 1677651234,
                    "team": "team_1234567890",
                    "owner": "user_1234567890",
                    "pending_receipts": {
                      "attempted": 2,
                      "succeeded": 2,
                      "failed": 0,
                      "skipped": 0,
                      "failures": []
                    },
                    "from": "api"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteClientsById",
        "tags": [
          "Clients"
        ],
        "summary": "Delete client",
        "description": "Delete a specific client.\n\n**gigstack Connect:** Delete other teams' clients using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "client_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Client deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "deleted": true
                  },
                  "message": "Client deleted successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/clients/search": {
      "get": {
        "operationId": "getClientsSearch",
        "tags": [
          "Clients"
        ],
        "summary": "Search clients",
        "description": "Full-text search across clients using Typesense. Provides fast, typo-tolerant search capabilities.\n\n**gigstack Connect:** Access other teams' clients using the `team` parameter.\n\n**Search Capabilities:**\n- Search across client name, email, tax ID, legal name, and metadata\n- Typo-tolerant fuzzy matching\n- Paginated results\n\n**Requirements:**\n- Typesense must be configured for your team\n- The `q` (or `query`) parameter is required\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/SearchQueryParam"
          },
          {
            "$ref": "#/components/parameters/SearchQueryBackwardCompatParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/SearchPageParam"
          },
          {
            "$ref": "#/components/parameters/FieldsParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Clients searched successfully",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SearchResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "message": "Clients searched successfully",
                  "data": [
                    {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    }
                  ],
                  "found": 1,
                  "page": 1,
                  "per_page": 10,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "missing_query": {
                    "summary": "Missing query parameter",
                    "value": {
                      "error": {
                        "code": "missing_query",
                        "message": "Query parameter is required"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "missing_typesense_key": {
                    "summary": "Typesense not configured",
                    "value": {
                      "error": {
                        "code": "missing_typesense_key",
                        "message": "Typesense API key not configured for this team"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/clients/validate/{id}": {
      "post": {
        "operationId": "createClientsValidateById",
        "tags": [
          "Clients"
        ],
        "summary": "Validate client fiscal information",
        "description": "Re-runs the full SAT validation for a client on demand. Performs three independent checks in parallel\nand persists the results on the client doc (`is_valid`, `efos`, `sat_status`):\n\n1. **Fiscal validation** — attempts to stamp a test CFDI against the PAC. Detects RFC/legal_name/CP mismatches with SAT registry.\n2. **EFOS check** — Art. 69-B blacklist lookup.\n3. **SAT lists** — fan-out lookup across 20 Datos Abiertos lists (Art. 69 Cancelados/Firmes/No localizados/CSD sin efectos/..., Art. 69-B Definitivos/Presuntos/..., Art. 69-B Bis). Lists are refreshed weekly from `sat.gob.mx`.\n\n**gigstack Connect:** Validate other teams' clients using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "client_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Client validated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Client info validated successfully"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "fiscal_validation": {
                          "type": "object",
                          "properties": {
                            "status": {
                              "type": "string",
                              "enum": [
                                "valid",
                                "not_valid",
                                "skipped"
                              ]
                            },
                            "message": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        },
                        "efos": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "is_valid": {
                              "type": "boolean",
                              "nullable": true
                            }
                          }
                        },
                        "sat_status": {
                          "type": "object",
                          "nullable": true,
                          "description": "See `sat_status` on `ApiPublicClient` for full shape."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Client info validated successfully",
                  "data": {
                    "fiscal_validation": {
                      "status": "not_valid",
                      "message": "Fiscal info validation failed. El campo DomicilioFiscalReceptor del receptor..."
                    },
                    "efos": {
                      "is_valid": false
                    },
                    "sat_status": {
                      "is_risky": true,
                      "efos": {
                        "is_valid": false
                      },
                      "hits": [
                        {
                          "list": "art_69b_definitivos",
                          "label": "Definitivos 69-B",
                          "source": "art_69b",
                          "is_risky": true,
                          "detail": {
                            "nombre_del_contribuyente": "ASESORES Y ADMINISTRADORES AGRICOLAS, S. DE R.L. DE C.V.",
                            "situacion_del_contribuyente": "Definitivo",
                            "publicacion_dof_definitivos": "28/06/2018"
                          }
                        }
                      ],
                      "checked_at": 1776887458784
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/clients/customerportal": {
      "post": {
        "operationId": "createClientsCustomerportal",
        "tags": [
          "Clients"
        ],
        "summary": "Get client customer portal access token",
        "description": "Generate a secure access token for client customer portal.\n\n**gigstack Connect:** Access other teams' customer portal using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "string",
                    "description": "Client ID to generate access token for.",
                    "example": "client_1234567890"
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Client email address",
                    "example": "client@example.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Portal session created. The link is valid for 5 days.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string"
                        },
                        "expires_at": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "session_id": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "url": "https://portal.gigstack.pro/cp_8f2k1m?sessionId=otpcustomerportal_5Yh2Kd&c=739154",
                    "expires_at": 1767657600000,
                    "session_id": "otpcustomerportal_5Yh2Kd"
                  },
                  "message": "Customer portal retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request - Missing email or team portal not configured",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Error getting customer portal"
                    },
                    "error": {
                      "type": "string",
                      "example": "Client ID or email is required"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Failed to get client customer portal"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/clients/csf": {
      "post": {
        "operationId": "createClientsCsf",
        "tags": [
          "Clients"
        ],
        "summary": "Upload CSF PDF to create or update client",
        "description": "Upload a CSF (Constancia de Situación Fiscal) PDF file from SAT to automatically extract fiscal information and create a new client or update an existing one.\n\n**How it works:**\n1. Upload the CSF PDF file as `multipart/form-data`\n2. The system extracts RFC and CIF from the PDF\n3. Validates the fiscal information against SAT\n4. Creates a new client or updates an existing one with the fiscal data\n\n**Query Parameters:**\n- `client_id` (optional): If provided, updates the existing client. If omitted, creates a new client.\n\n**Extracted Information:**\n- Legal name (Razón Social)\n- RFC (Tax ID)\n- Fiscal regime (Régimen Fiscal)\n- Fiscal type (company/individual)\n- Fiscal status\n- Complete address (street, exterior/interior number, neighborhood, city, state, zip code)\n\n**gigstack Connect:** Create or update clients for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "client_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional client ID to update. If not provided, creates a new client."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "CSF PDF file from SAT"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing client (`client_id`) updated with the CSF data. Standardized envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicClient"
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "client_1234567890",
                    "name": "ESCUELA KEMPER URGATE",
                    "legal_name": "ESCUELA KEMPER URGATE",
                    "email": "contabilidad@ejemplo.com",
                    "bcc": [],
                    "phone": "+524421234567",
                    "tax_id": "EKU9003173C9",
                    "tax_system": "601",
                    "use": "G03",
                    "address": {
                      "street": "Av. Constituyentes",
                      "exterior": "1000",
                      "neighborhood": "Centro",
                      "city": "Querétaro",
                      "state": "QRO",
                      "zip": "76000",
                      "country": "MEX"
                    },
                    "is_valid": false,
                    "efos": {
                      "is_valid": true
                    },
                    "metadata": {
                      "rfc": "EKU9003173C9",
                      "fiscal_type": "company",
                      "fiscal_status": "Activo"
                    },
                    "livemode": true,
                    "from": "api",
                    "owner": "user_1234567890",
                    "team": "team_1234567890",
                    "created_at": 1767225600000
                  },
                  "message": "Client updated with CSF data",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "201": {
            "description": "Client created from the CSF. Standardized envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicClient"
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "client_1234567890",
                    "name": "ESCUELA KEMPER URGATE",
                    "legal_name": "ESCUELA KEMPER URGATE",
                    "email": "contabilidad@ejemplo.com",
                    "bcc": [],
                    "phone": "+524421234567",
                    "tax_id": "EKU9003173C9",
                    "tax_system": "601",
                    "use": "G03",
                    "address": {
                      "street": "Av. Constituyentes",
                      "exterior": "1000",
                      "neighborhood": "Centro",
                      "city": "Querétaro",
                      "state": "QRO",
                      "zip": "76000",
                      "country": "MEX"
                    },
                    "is_valid": false,
                    "efos": {
                      "is_valid": true
                    },
                    "metadata": {
                      "rfc": "EKU9003173C9",
                      "fiscal_type": "company",
                      "fiscal_status": "Activo"
                    },
                    "livemode": true,
                    "from": "api",
                    "owner": "user_1234567890",
                    "team": "team_1234567890",
                    "created_at": 1767225600000
                  },
                  "message": "Client created from CSF",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid file, missing fiscal data, or client not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "no_file": {
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Error processing CSF upload"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "invalid_pdf": {
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Error processing CSF upload"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "missing_data": {
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Error processing CSF upload"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "client_not_found": {
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Error processing CSF upload"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/clients/{id}/stamp-pending-receipts": {
      "post": {
        "tags": [
          "Clients"
        ],
        "summary": "Stamp pending receipts",
        "operationId": "stampClientPendingReceipts",
        "description": "Stamp the client's pending receipts into CFDI invoices.\n\n**Batch cap:** at most **100** receipts are stamped per call. Receipts are processed\nfive at a time. If the client has more than 100 pending receipts, call the endpoint\nrepeatedly until `data.remaining` reaches `0`.\n\n`data.remaining` is re-counted from Firestore *after* stamping, so it includes both\nreceipts beyond the 100-item cap and receipts that failed in this run (they stay\n`pending`).\n\n**Fiscal prerequisites.** Before stamping anything the handler checks that the client\nhas an RFC (`rfc`, falling back to `tax_id`), a legal name (`legal_name`, falling back\nto `name`), `address.zip`, and `tax_system`. If any is missing it returns `400` with\n`error.code: client_fiscal_data_incomplete` and stamps nothing. `email` and\n`address.country` are not checked (`country` defaults to `MEX`).\n\n**gigstack Connect:** Stamp other teams' client receipts using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Client id.",
            "schema": {
              "type": "string"
            },
            "example": "client_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Batch processed. A `200` does **not** mean every receipt was stamped — inspect\n`data.failed` and `data.results`. When the client has no pending receipts the\nresponse is still `200`, with all counters at `0` and the message\n`No pending receipts found`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string",
                          "description": "`Stamped N receipt(s)`, `Stamped N receipt(s), M failed`, or `No pending receipts found`.",
                          "example": "Stamped 2 receipt(s), 1 failed"
                        },
                        "data": {
                          "type": "object",
                          "required": [
                            "stamped",
                            "failed",
                            "remaining",
                            "results"
                          ],
                          "properties": {
                            "stamped": {
                              "type": "integer",
                              "description": "Receipts successfully stamped in this call.",
                              "example": 2
                            },
                            "failed": {
                              "type": "integer",
                              "description": "Receipts that failed to stamp in this call.",
                              "example": 1
                            },
                            "remaining": {
                              "type": "integer",
                              "description": "Receipts still `pending` for this client after the call.",
                              "example": 0
                            },
                            "results": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "id",
                                  "status"
                                ],
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "example": "receipt_1234567890"
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "stamped",
                                      "failed"
                                    ],
                                    "example": "stamped"
                                  },
                                  "error": {
                                    "type": "string",
                                    "description": "Present only when `status` is `failed`.",
                                    "example": "CFDI40147 - El campo UsoCFDI no es válido"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "message": "Stamped 2 receipt(s), 1 failed",
                  "timestamp": 1767225600000,
                  "data": {
                    "stamped": 2,
                    "failed": 1,
                    "remaining": 0,
                    "results": [
                      {
                        "id": "receipt_1234567890",
                        "status": "stamped"
                      },
                      {
                        "id": "receipt_2345678901",
                        "status": "stamped"
                      },
                      {
                        "id": "receipt_3456789012",
                        "status": "failed",
                        "error": "CFDI40147 - El campo UsoCFDI no es válido"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "The client is missing fiscal information required to stamp. Nothing is stamped.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "client_fiscal_data_incomplete",
                    "message": "Client is missing fiscal information required to stamp",
                    "details": "Missing field(s): rfc, tax_system"
                  },
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Client not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        }
      }
    },
    "/clients/{id}/support-documents": {
      "post": {
        "operationId": "createClientsByIdSupportDocuments",
        "tags": [
          "Clients"
        ],
        "summary": "Upload support document",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nUpload a supporting document (contract, proof of delivery, etc.) for a client.\n\n**SAT 2026 Compliance:** Documents uploaded to a client are automatically inherited by all\nof the client's invoices and payments, simplifying compliance management.\n\n**gigstack Connect:** Upload documents for other teams' clients using the `team` parameter.\n\n**Supported File Types:**\n- PDF files (.pdf)\n- Images (.png, .jpg, .jpeg, .webp)\n\n**File Size Limit:** 10MB\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Client ID",
            "example": "client_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UploadSupportDocumentInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document uploaded. Standardized envelope (`timestamp` in epoch ms).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/SATDocument"
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "doc_1234567890",
                    "document_type": "contract",
                    "name": "Contrato de servicios 2026",
                    "description": null,
                    "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_1234567890%2Fdocuments%2Fcontrato-2026.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                    "file_name": "contrato-2026.pdf",
                    "file_size": 284913,
                    "mime_type": "application/pdf",
                    "compliance_status": "pending_review",
                    "created_at": 1767225600000,
                    "linked_entities": [
                      {
                        "entity_type": "client",
                        "entity_id": "client_1234567890",
                        "linked_at": 1767225600000
                      }
                    ]
                  },
                  "message": "Support document uploaded successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Client not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      },
      "get": {
        "operationId": "getClientsByIdSupportDocuments",
        "tags": [
          "Clients"
        ],
        "summary": "List support documents",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nRetrieve all supporting documents attached to a client.\n\n**gigstack Connect:** View documents for other teams' clients using the `team` parameter.\n\nDocuments are returned sorted by creation date (newest first).\n\n**Note:** Client documents are automatically inherited by all the client's invoices and payments.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Client ID",
            "example": "client_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Documents retrieved, newest first. Standardized envelope (`timestamp` in epoch ms).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SATDocument"
                      }
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "doc_1234567890",
                      "document_type": "contract",
                      "name": "Contrato de servicios 2026",
                      "description": null,
                      "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_1234567890%2Fdocuments%2Fcontrato-2026.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                      "file_name": "contrato-2026.pdf",
                      "file_size": 284913,
                      "mime_type": "application/pdf",
                      "compliance_status": "pending_review",
                      "created_at": 1767225600000,
                      "linked_entities": [
                        {
                          "entity_type": "client",
                          "entity_id": "client_1234567890",
                          "linked_at": 1767225600000
                        }
                      ]
                    }
                  ],
                  "message": "Support documents retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Client not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/services": {
      "get": {
        "operationId": "listServices",
        "tags": [
          "Services"
        ],
        "summary": "List services",
        "description": "Retrieve a paginated list of services.\n\n**gigstack Connect:** Access other teams' services using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGtParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLtParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Services retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Services retrieved successfully"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiPublicService"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "example": false
                    },
                    "total_results": {
                      "type": "integer",
                      "example": 10
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "example": null
                    }
                  }
                },
                "example": {
                  "message": "Services retrieved successfully",
                  "data": [
                    {
                      "id": "service_1234567890",
                      "description": "Professional consulting services",
                      "sku": "CONS-001",
                      "product_key": "80141503",
                      "unit_key": "E48",
                      "unit_name": "Servicio",
                      "unit_price": 1000,
                      "quantity": 1,
                      "taxes": [
                        {
                          "type": "IVA",
                          "rate": 0.16,
                          "factor": "Tasa",
                          "withholding": false
                        }
                      ],
                      "team": "team_1234567890",
                      "created_at": 1677651234,
                      "from": "api"
                    }
                  ],
                  "has_more": false,
                  "total_results": 1
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createServices",
        "tags": [
          "Services"
        ],
        "summary": "Create service",
        "description": "Create a new service.\n\n**gigstack Connect:** Create services for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ServiceInput"
              },
              "example": {
                "description": "Professional consulting services",
                "sku": "CONS-001",
                "product_key": "80141503",
                "unit_key": "ACT",
                "unit_name": "Actividad",
                "unit_price": 1500,
                "taxes": [
                  {
                    "type": "IVA",
                    "rate": 0.16,
                    "factor": "Tasa",
                    "withholding": false,
                    "inclusive": false
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Service created. Standardized envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "message": {
                      "type": "string",
                      "example": "Service created"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicService"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Service created",
                  "data": {
                    "id": "service_1234567890",
                    "description": "Professional consulting services",
                    "sku": "CONS-001",
                    "product_key": "80141503",
                    "unit_key": "E48",
                    "unit_name": "Servicio",
                    "unit_price": 1000,
                    "quantity": 1,
                    "taxes": [
                      {
                        "type": "IVA",
                        "rate": 0.16,
                        "factor": "Tasa",
                        "withholding": false
                      }
                    ],
                    "team": "team_1234567890",
                    "created_at": 1677651234,
                    "from": "api"
                  },
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Body validation failed (`error.code: validation_failed`, message `Invalid body`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "validation_failed",
                    "message": "Invalid body",
                    "details": [
                      "unit_price: Expected number"
                    ]
                  },
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/services/{id}": {
      "get": {
        "operationId": "getServicesById",
        "tags": [
          "Services"
        ],
        "summary": "Get service",
        "description": "Retrieve a specific service by ID.\n\n**gigstack Connect:** Access other teams' services using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "service_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Service retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Service retrieved successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicService"
                    }
                  }
                },
                "example": {
                  "message": "Service retrieved successfully",
                  "data": {
                    "id": "service_1234567890",
                    "description": "Professional consulting services",
                    "sku": "CONS-001",
                    "product_key": "80141503",
                    "unit_key": "E48",
                    "unit_name": "Servicio",
                    "unit_price": 1000,
                    "quantity": 1,
                    "taxes": [
                      {
                        "type": "IVA",
                        "rate": 0.16,
                        "factor": "Tasa",
                        "withholding": false
                      }
                    ],
                    "team": "team_1234567890",
                    "created_at": 1677651234,
                    "from": "api"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "put": {
        "operationId": "updateServicesById",
        "tags": [
          "Services"
        ],
        "summary": "Update service",
        "description": "Update an existing service.\n\n**gigstack Connect:** Update other teams' services using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "service_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ServiceInput"
              },
              "example": {
                "description": "Updated consulting services - Premium package",
                "sku": "CONS-001-PREMIUM",
                "product_key": "80141503",
                "unit_key": "ACT",
                "unit_name": "Actividad",
                "unit_price": 2500,
                "taxes": [
                  {
                    "type": "IVA",
                    "rate": 0.16,
                    "factor": "Tasa",
                    "withholding": false,
                    "inclusive": false
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated. Raw body (no `success`/`timestamp`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data"
                  ],
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicService"
                    }
                  }
                },
                "example": {
                  "message": "Service updated successfully",
                  "data": {
                    "id": "service_1234567890",
                    "description": "Servicios de consultoría profesional",
                    "quantity": 1,
                    "unit_price": 1000,
                    "product_key": "80141503",
                    "unit_key": "E48",
                    "unit_name": "Unidad de servicio",
                    "taxes": [
                      {
                        "type": "IVA",
                        "rate": 0.16,
                        "factor": "Tasa",
                        "withholding": false
                      }
                    ],
                    "team": "team_1234567890",
                    "created_at": 1767225600000,
                    "from": "api"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Body validation failed. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": "Invalid request body",
                  "errors": [
                    {
                      "path": "unit_price",
                      "code": "invalid_type",
                      "message": "Expected number"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure. Raw body (the message says \"client\" for services; this is the text the API returns).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Failed to update client"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteServicesById",
        "tags": [
          "Services"
        ],
        "summary": "Delete service",
        "description": "Delete a specific service.\n\n**gigstack Connect:** Delete other teams' services using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "service_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Service deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "deleted": true
                  },
                  "message": "Service deleted successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/sat": {
      "get": {
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "List SAT invoices",
        "description": "Returns invoices downloaded from SAT via Descarga Masiva. Supports filtering by direction,\nstatus, invoice type, RFC, and date range. Uses cursor-based pagination.\n\nRequires Descarga Masiva to be activated and at least one download request to have completed.\n",
        "operationId": "listSatInvoices",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "direction",
            "in": "query",
            "description": "Filter by invoice direction",
            "schema": {
              "type": "string",
              "enum": [
                "issued",
                "received"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by SAT invoice status",
            "schema": {
              "type": "string",
              "enum": [
                "Vigente",
                "Cancelado"
              ]
            }
          },
          {
            "name": "invoice_type",
            "in": "query",
            "description": "Filter by CFDI type code",
            "schema": {
              "type": "string",
              "enum": [
                "I",
                "E",
                "P",
                "N",
                "T"
              ]
            }
          },
          {
            "name": "issuer_rfc",
            "in": "query",
            "description": "Filter by issuer RFC",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "receiver_rfc",
            "in": "query",
            "description": "Filter by receiver RFC",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "Issue date from (inclusive), format YYYY-MM-DD",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "Issue date to (inclusive), format YYYY-MM-DD",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Number of results per page (1–100, default 20)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "description": "UUID of the last invoice from the previous page (cursor pagination)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of SAT invoices",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SatInvoice"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "description": "UUID to pass as starting_after for the next page"
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "6741A863-04BE-49FE-BB76-E1657AB6B7EA",
                      "uuid": "6741A863-04BE-49FE-BB76-E1657AB6B7EA",
                      "direction": "received",
                      "issuer": {
                        "rfc": "EKU9003173C9",
                        "name": "ESCUELA KEMPER URGATE"
                      },
                      "receiver": {
                        "rfc": "MEE200101ABC",
                        "name": "MI EMPRESA EJEMPLO SA DE CV"
                      },
                      "invoice_type": "I",
                      "series": "F",
                      "folio": "1024",
                      "subtotal": 103.44,
                      "total": 120,
                      "currency": "MXN",
                      "issue_date": "2025-01-15",
                      "stamp_date": "2025-01-15T12:34:56",
                      "status": "Vigente",
                      "pac_rfc": "SAT970701NN3",
                      "version": "4.0",
                      "certificate_number": "00001000000513342038",
                      "download_request_id": "satreq_abc123",
                      "has_xml": true,
                      "created_at": 1767225600000,
                      "updated_at": 1767225600000
                    }
                  ],
                  "has_more": true,
                  "next": "6741A863-04BE-49FE-BB76-E1657AB6B7EA",
                  "count": 1
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "description": "Internal server error"
          }
        }
      }
    },
    "/invoices/sat/{uuid}": {
      "get": {
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Get a SAT invoice",
        "description": "Returns a single invoice downloaded from SAT by its UUID.",
        "operationId": "getSatInvoice",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "description": "The SAT invoice UUID",
            "schema": {
              "type": "string"
            },
            "example": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e"
          }
        ],
        "responses": {
          "200": {
            "description": "SAT invoice",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/SatInvoice"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "6741A863-04BE-49FE-BB76-E1657AB6B7EA",
                    "uuid": "6741A863-04BE-49FE-BB76-E1657AB6B7EA",
                    "direction": "received",
                    "issuer": {
                      "rfc": "EKU9003173C9",
                      "name": "ESCUELA KEMPER URGATE"
                    },
                    "receiver": {
                      "rfc": "MEE200101ABC",
                      "name": "MI EMPRESA EJEMPLO SA DE CV"
                    },
                    "invoice_type": "I",
                    "series": "F",
                    "folio": "1024",
                    "subtotal": 103.44,
                    "total": 120,
                    "currency": "MXN",
                    "issue_date": "2025-01-15",
                    "stamp_date": "2025-01-15T12:34:56",
                    "status": "Vigente",
                    "pac_rfc": "SAT970701NN3",
                    "version": "4.0",
                    "certificate_number": "00001000000513342038",
                    "download_request_id": "satreq_abc123",
                    "has_xml": true,
                    "created_at": 1767225600000,
                    "updated_at": 1767225600000
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Invoice not found"
          }
        }
      }
    },
    "/invoices/import": {
      "post": {
        "operationId": "importInvoiceXml",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Import CFDI XMLs the team already holds",
        "description": "Imports up to 50 stamped CFDI XMLs and files each one by the team's RFC:\n\n- **Team is the issuer** → stored as an invoice (`GET /invoices/{id}`), with its XML.\n- **Team is the receiver** → stored with the SAT received invoices (`GET /invoices/sat`), already imported, so Descarga Masiva will not download or bill it again.\n- **Neither** → rejected; nothing is written.\n\nNothing is billed. A UUID the team already holds is reported as `already_exists`; one held by another account as `conflict`. Received nómina XMLs are rejected because they contain employee personal data. Status is assumed `Vigente`: an XML cannot show a later cancellation.\n\nSend each file as `xml` (the XML text) or `content` (base64).\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "files"
                ],
                "properties": {
                  "files": {
                    "type": "array",
                    "maxItems": 50,
                    "items": {
                      "type": "object",
                      "properties": {
                        "filename": {
                          "type": "string",
                          "example": "factura-a12.xml"
                        },
                        "xml": {
                          "type": "string",
                          "description": "The CFDI XML as text"
                        },
                        "content": {
                          "type": "string",
                          "description": "The CFDI XML, base64-encoded. Used when `xml` is absent."
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-file outcome",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "summary": {
                          "type": "object",
                          "properties": {
                            "imported": {
                              "type": "integer"
                            },
                            "issued": {
                              "type": "integer"
                            },
                            "received": {
                              "type": "integer"
                            },
                            "already_exists": {
                              "type": "integer"
                            },
                            "not_imported": {
                              "type": "integer"
                            }
                          }
                        },
                        "results": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "filename": {
                                "type": "string"
                              },
                              "success": {
                                "type": "boolean"
                              },
                              "action": {
                                "type": "string",
                                "enum": [
                                  "created",
                                  "completed",
                                  "already_exists",
                                  "conflict",
                                  "rejected"
                                ]
                              },
                              "direction": {
                                "type": "string",
                                "nullable": true,
                                "enum": [
                                  "issued",
                                  "received",
                                  null
                                ]
                              },
                              "uuid": {
                                "type": "string",
                                "nullable": true
                              },
                              "error": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Imported 2 of 3 files",
                  "data": {
                    "summary": {
                      "imported": 2,
                      "issued": 1,
                      "received": 1,
                      "already_exists": 0,
                      "not_imported": 1
                    },
                    "results": [
                      {
                        "filename": "a12.xml",
                        "success": true,
                        "action": "created",
                        "direction": "issued",
                        "uuid": "6F1B2C3D-0000-4000-8000-000000000001",
                        "error": null
                      },
                      {
                        "filename": "proveedor.xml",
                        "success": true,
                        "action": "created",
                        "direction": "received",
                        "uuid": "6F1B2C3D-0000-4000-8000-000000000002",
                        "error": null
                      },
                      {
                        "filename": "otro.xml",
                        "success": false,
                        "action": "rejected",
                        "direction": null,
                        "uuid": "6F1B2C3D-0000-4000-8000-000000000003",
                        "error": "El RFC AAA010101AAA no aparece como emisor ni receptor de este CFDI"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or malformed files, more than 50 files, or no RFC on the team"
          }
        }
      }
    },
    "/invoices/sat/{uuid}/retry-xml": {
      "post": {
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Retry XML download",
        "description": "Manually retry the XML download for a received SAT invoice stuck in processing or error state.",
        "operationId": "retrySatXmlDownload",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "description": "The SAT invoice UUID",
            "schema": {
              "type": "string"
            },
            "example": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e"
          }
        ],
        "responses": {
          "200": {
            "description": "XML downloaded, or already present. When the invoice already had its XML the\nhandler short-circuits with `message: Invoice already has XML downloaded.` and\n`data.resource_status: ready` without re-fetching or charging a credit.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "message"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "XML downloaded successfully"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "resource_status": {
                          "type": "string",
                          "enum": [
                            "ready"
                          ],
                          "example": "ready"
                        },
                        "credit_charged": {
                          "type": "boolean",
                          "example": true
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "XML downloaded successfully",
                  "data": {
                    "resource_status": "ready",
                    "credit_charged": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Either the invoice is issued rather than received\n(`Issued invoices do not require XML retry — they already have their XML.`) or the\nteam has no usable FIEL\n(`FIEL credentials not found or expired. Upload FIEL first using POST /v2/invoices/download/fiel`).\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "message": "FIEL credentials not found or expired. Upload FIEL first using POST /v2/invoices/download/fiel"
                }
              }
            }
          },
          "401": {
            "description": "`{ \"success\": false, \"message\": \"Unauthorized\" }`."
          },
          "403": {
            "description": "`{ \"success\": false, \"message\": \"Forbidden\" }` — the invoice belongs to another team."
          },
          "404": {
            "description": "`{ \"success\": false, \"message\": \"SAT invoice not found\" }`."
          },
          "422": {
            "description": "The XML fetch from SAT failed. The invoice is marked `resource_status: error`;\n`message` is `XML download failed` and `error` carries the upstream reason.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "message": {
                      "type": "string",
                      "example": "XML download failed"
                    },
                    "error": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "resource_status": {
                          "type": "string",
                          "enum": [
                            "error"
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": false,
                  "message": "XML download failed",
                  "error": "SAT rejected the download request for this UUID",
                  "data": {
                    "resource_status": "error"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal error while retrying the XML download."
          }
        }
      }
    },
    "/invoices/sat/{uuid}/pdf": {
      "post": {
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Generate PDF for a received SAT invoice",
        "description": "Generates a PDF from the stored XML of a received SAT invoice.\nThe result is cached — subsequent calls return the cached PDF instantly.\nRequires the XML to have been downloaded first (`hasXml: true`).\n",
        "operationId": "generateSatPdf",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "description": "The SAT invoice UUID",
            "schema": {
              "type": "string"
            },
            "example": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e"
          }
        ],
        "responses": {
          "200": {
            "description": "PDF generated, or served from cache. The success body is **not** enveloped — it is\njust `{ \"pdf\": \"<base64>\" }`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "pdf"
                  ],
                  "properties": {
                    "pdf": {
                      "type": "string",
                      "description": "Base64-encoded PDF file",
                      "example": "JVBERi0xLjQKJcOkw..."
                    }
                  }
                },
                "example": {
                  "pdf": "JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PC9UeXBlIC9DYXRhbG9nPj4K..."
                }
              }
            }
          },
          "401": {
            "description": "`{ \"success\": false, \"message\": \"Unauthorized\" }`."
          },
          "403": {
            "description": "`{ \"success\": false, \"message\": \"Forbidden\" }` — the invoice belongs to another team."
          },
          "404": {
            "description": "`{ \"success\": false, \"message\": \"SAT invoice not found\" }`, or\n`{ \"success\": false, \"message\": \"XML not yet available\" }` when the XML has not been\ndownloaded yet — call `POST /v2/invoices/sat/{uuid}/retry-xml` first.\n"
          },
          "500": {
            "description": "`{ \"success\": false, \"message\": \"<error>\" }` or `Internal error`."
          },
          "502": {
            "description": "**Upstream PDF renderer failure.** The CFDI-to-PDF service returned a non-OK\nresponse (`PDF generator error: <body>`) or an empty payload\n(`PDF generator returned no data`). The stored XML is intact — retry later.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "message": "PDF generator returned no data"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/errors": {
      "get": {
        "operationId": "getInvoicesErrors",
        "tags": [
          "Invoices"
        ],
        "summary": "List CFDI errors",
        "description": "Retrieve a paginated and filterable list of CFDI errors from the error matrix.\nUse this endpoint to search for error codes, understand error causes, and find solutions.\n\n**Query Options:**\n- Filter by exact error code using `code` parameter\n- Search across all fields using `q` parameter\n- Filter by error type (invoice, receiver, sender, unknown)\n- Paginate results with `limit` and `page` parameters\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "code",
            "in": "query",
            "description": "Filter by exact error code (e.g., CFDI140223). Returns single document if found.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Search query. Searches across code, description, explanation, and solution fields.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "Filter by error type",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "invoice",
                "receiver",
                "sender",
                "unknown"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Number of results per page (max 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "CFDI errors retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "total",
                    "page",
                    "limit",
                    "message",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CfdiError"
                      }
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total count of matching errors",
                      "example": 150
                    },
                    "page": {
                      "type": "integer",
                      "description": "Current page number",
                      "example": 1
                    },
                    "limit": {
                      "type": "integer",
                      "description": "Items per page",
                      "example": 50
                    },
                    "message": {
                      "type": "string",
                      "example": "CFDI errors retrieved successfully"
                    },
                    "timestamp": {
                      "type": "number",
                      "format": "int64",
                      "description": "Unix timestamp in milliseconds",
                      "example": 1734605400000
                    }
                  }
                },
                "examples": {
                  "singleError": {
                    "summary": "Single error by code",
                    "value": {
                      "success": true,
                      "data": [
                        {
                          "code": "CFDI140223",
                          "description": "El campo Rfc del receptor no es valido",
                          "explanation": "The RFC (tax ID) provided for the receiver does not meet the validation requirements or format specified by SAT",
                          "solution": "Verify that the receiver's RFC is correct, properly formatted (13 characters for individuals, 12 for legal entities), and matches SAT's registered information",
                          "type": "receiver"
                        }
                      ],
                      "total": 1,
                      "page": 1,
                      "limit": 1,
                      "message": "CFDI error retrieved successfully",
                      "timestamp": 1767225600000
                    }
                  },
                  "searchResults": {
                    "summary": "Search results",
                    "value": {
                      "success": true,
                      "data": [
                        {
                          "code": "CFDI140223",
                          "description": "El campo Rfc del receptor no es valido",
                          "explanation": "The RFC (tax ID) provided for the receiver does not meet the validation requirements",
                          "solution": "Verify that the receiver's RFC is correct and properly formatted",
                          "type": "receiver"
                        },
                        {
                          "code": "CFDI140225",
                          "description": "El RFC del receptor no existe en el padron del SAT",
                          "explanation": "The receiver's RFC is not registered in SAT's taxpayer registry",
                          "solution": "Confirm the RFC is registered with SAT or contact the receiver to verify their tax information",
                          "type": "receiver"
                        }
                      ],
                      "total": 2,
                      "page": 1,
                      "limit": 10,
                      "message": "CFDI errors retrieved successfully",
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Error code not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "CFDI Error not found"
                    },
                    "error": {
                      "type": "string",
                      "example": "Error code 'INVALID_CODE' not found"
                    },
                    "timestamp": {
                      "type": "number",
                      "format": "int64",
                      "description": "Unix timestamp in milliseconds",
                      "example": 1734605400000
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/income": {
      "get": {
        "operationId": "getInvoicesIncome",
        "tags": [
          "Invoices"
        ],
        "summary": "List income invoices",
        "description": "Retrieve a paginated list of income invoices with powerful filtering capabilities.\n\n**gigstack Connect:** Access other teams' invoices using the `team` parameter.\n\n**Filtering Options:**\n- Filter by creation date using comparison operators\n- Filter by `status`, `series`, `folio` and `idempotency_key` (exact match only)\n- Filter by metadata fields using dot or underscore notation (e.g., `metadata.order_id` or `metadata_order_id`)\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "$ref": "#/components/parameters/ClientIdFilterParam"
          },
          {
            "$ref": "#/components/parameters/TaxIdFilterParam"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by invoice status. `cancelled` is accepted as an alias of `canceled`.\n",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "valid",
                "canceled",
                "cancelled"
              ]
            }
          },
          {
            "name": "series",
            "in": "query",
            "description": "Filter by exact invoice series (no prefix matching).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "folio",
            "in": "query",
            "description": "Filter by exact folio number (no prefix matching).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "idempotency_key",
            "in": "query",
            "description": "Filter by the exact idempotency key the invoice was created with.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "metadata.{key}",
            "in": "query",
            "description": "Filter by any metadata field using dot notation (e.g., `metadata.order_id=ORD-123`)\nor underscore notation (e.g., `metadata_order_id=ORD-123`).\nBoth formats are supported and equivalent.\nUses Typesense search for efficient querying without requiring Firestore indexes.\n",
            "required": false,
            "schema": {
              "type": "string"
            },
            "style": "form"
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination when using metadata filters (default 1).\nOnly applies when filtering by metadata fields.\n",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invoices retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                },
                "example": {
                  "success": true,
                  "message": "Invoices retrieved successfully",
                  "data": [
                    {
                      "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                      "idempotency_key": null,
                      "client": {
                        "id": "client_1234567890",
                        "name": "ESCUELA KEMPER URGATE",
                        "legal_name": "ESCUELA KEMPER URGATE",
                        "email": "contabilidad@ejemplo.com",
                        "bcc": [],
                        "phone": "+524421234567",
                        "tax_id": "EKU9003173C9",
                        "tax_system": "601",
                        "use": "G03",
                        "address": {
                          "street": "Av. Constituyentes",
                          "exterior": "1000",
                          "neighborhood": "Centro",
                          "city": "Querétaro",
                          "state": "QRO",
                          "zip": "76000",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "efos": {
                          "is_valid": true
                        },
                        "metadata": {},
                        "livemode": true,
                        "from": "api",
                        "owner": "user_1234567890",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      },
                      "created_at": 1767225600000,
                      "date": 1767225600000,
                      "currency": "MXN",
                      "exchange_rate": 1,
                      "total": 1160,
                      "subtotal": 1000,
                      "discount": 0,
                      "taxes": 160,
                      "withholding_taxes": 0,
                      "series": "A",
                      "folio_number": 123,
                      "invoice_type": "I",
                      "use": "G03",
                      "payment_form": "03",
                      "payment_method": "PUE",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "from": "api",
                      "status": "valid",
                      "payments": [
                        "payment_1234567890"
                      ],
                      "invoices": [],
                      "items": [
                        {
                          "id": "service_1234567890",
                          "description": "Servicios de consultoría profesional",
                          "quantity": 1,
                          "unit_price": 1000,
                          "product_key": "80141503",
                          "unit_key": "E48"
                        }
                      ],
                      "metadata": {},
                      "emails": [
                        "contabilidad@ejemplo.com"
                      ],
                      "cancellation": null,
                      "stamp": {
                        "sello": "kQ3xZ9vR2mP7tL4wN8cB1yH6",
                        "stamp_at": 1767225600000
                      },
                      "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB&re=MEE200101ABC&rr=EKU9003173C9&tt=1160.00&fe=kQ3xZ9"
                    }
                  ],
                  "next": null,
                  "has_more": false,
                  "total_results": 1,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createInvoicesIncome",
        "tags": [
          "Invoices"
        ],
        "summary": "Create income invoice",
        "description": "[Small working example](/recipes/paid-later)\n\n**Integration note:** This endpoint stamps immediately. For a reviewable document, create a draft first. Successful issuance returns HTTP 200 and data.uuid. Fiscal validity does not establish that payment has been received. Read [shared fields](/concepts/shared-fields) and the [Mexico](/countries/mexico) or [Colombia](/countries/colombia) guide for country-specific meaning. The linked fiscal recipes and staging issuance results use a Mexican issuer.\n\nCreate a new income invoice with CFDI 4.0 compliance.\n\n**Safe retries with `idempotency_key`.** Send your own identifier for the invoice (for example your\norder id) in `idempotency_key`. gigstack claims the key before charging a credit or stamping, so\nrepeating the request cannot issue a second CFDI or charge twice:\n\n- The invoice already exists: `400` with `message.duplicate: true` and `message.uuid`.\n- Another request with the key is still being processed: `409` `idempotency_in_progress`. Retry later.\n- The PAC's answer was lost: `503` `PAC_OUTCOME_UNKNOWN` with `retryable: true`. Retry with the same\n  key: the same XML and folio are sent again, so the PAC stamps it once or returns the stamp it already made.\n- The PAC can't confirm an earlier attempt: `409` `STAMP_NEEDS_REVIEW`. Don't retry; contact support.\n- The SAT or PAC rejected the data: `400`, and the key is free again for a corrected request.\n\nWithout an `idempotency_key` none of this applies, and after a `503` `PAC_OUTCOME_UNKNOWN`\n(`retryable: false`) you can't tell whether the invoice exists: look it up before sending it again.\n\nTo issue many invoices at once, use `POST /invoices/income/batch`.\n\n**gigstack Connect:** Create invoices for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceIncomeInput"
              },
              "example": {
                "automation_type": "payment",
                "currency": "MXN",
                "use": "G03",
                "payment_form": "03",
                "payment_method": "PUE",
                "client": {
                  "id": "client_1234567890"
                },
                "items": [
                  {
                    "description": "Professional consulting services",
                    "sku": "CONS-001",
                    "product_key": "80141503",
                    "unit_key": "ACT",
                    "unit_name": "Actividad",
                    "unit_price": 1500,
                    "taxability": "02",
                    "taxes": [
                      {
                        "type": "IVA",
                        "rate": 0.16,
                        "factor": "Tasa",
                        "withholding": false,
                        "inclusive": false
                      }
                    ],
                    "quantity": 1
                  }
                ],
                "send_email": true,
                "emails": [
                  "cliente@empresa.com"
                ],
                "metadata": {
                  "project_id": "PROJ-2024-001",
                  "department": "consulting"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Invoice created successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicIncomeInvoice"
                    }
                  }
                },
                "example": {
                  "message": "Invoice created successfully",
                  "data": {
                    "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                    "client": {
                      "id": "client_1234567890",
                      "name": "Juan Pérez García",
                      "email": "juan.perez@ejemplo.com",
                      "tax_id": "PEGJ800101ABC",
                      "from": "api",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "status": "valid",
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "total": 1160,
                    "subtotal": 1000,
                    "taxes": 160,
                    "discount": 0,
                    "series": "A",
                    "folio_number": 123,
                    "invoice_type": "I",
                    "payment_method": "PUE",
                    "items": [
                      {
                        "id": "item_1234567890",
                        "description": "Professional consulting services",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48"
                      }
                    ],
                    "created_at": 1677651234,
                    "livemode": true,
                    "owner": "user_1234567890"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request. All bodies here are **raw**, not the standardized envelope.\n- Body validation: `{ \"message\": \"Invalid body\", \"errors\": [ { \"path\": …, \"code\": …, \"message\": … } ] }`.\n  Unknown keys are rejected — there is no `client_id` field; use `client: { \"id\": … }`.\n- `{ \"message\": \"Billing account not found\", \"error\": \"Billing account is required\" }`\n- `{ \"message\": \"Invalid currency\", \"error\": … }`\n- `{ \"message\": \"Exchange rate not found\" }`\n- `{ \"message\": \"Resource resolution failed\", \"error\": … }` when the client/service\n  reference is ambiguous (both `id` and `search`, or `safety_check` matched several).\n- Generic CFDI/PAC stamping failure, nested one level under `message`:\n  `{ \"message\": { \"error\": …, \"code\": …, \"providerMessage\": …, \"retryable\": false } }`.\n  A rejection frees the `idempotency_key`: a corrected request may reuse it.\n- **Duplicate `idempotency_key`.** An invoice already exists under the key. Same CFDI shape,\n  `code: INVALID_INVOICE`, plus `duplicate: true` and the existing invoice's `uuid`. Nothing was\n  stamped or charged. Treat it as success and read the invoice with `GET /invoices/income/{id}`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LegacyErrorResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "message": {
                          "$ref": "#/components/schemas/CfdiErrorResponse"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "invalid_body": {
                    "summary": "Body validation",
                    "value": {
                      "message": "Invalid body",
                      "errors": [
                        {
                          "path": "client_id",
                          "code": "unexpected_key",
                          "message": "Unexpected field"
                        }
                      ]
                    }
                  },
                  "sat_rejection": {
                    "summary": "The SAT rejected the document's data",
                    "value": {
                      "message": {
                        "error": "Error al timbrar la factura: CFDI40147 - El campo UsoCFDI no es válido [pcs_8f2a1c]",
                        "code": "CFDI40147",
                        "providerMessage": "CFDI40147 - El campo UsoCFDI no es válido",
                        "retryable": false
                      }
                    }
                  },
                  "duplicate_idempotency_key": {
                    "summary": "An invoice already exists under this idempotency_key",
                    "value": {
                      "message": {
                        "error": "Error al timbrar la factura: Ya existe un comprobante con la misma idempotencia (uuid: 0f8fad5b-d9cb-469f-a165-70867728950e)",
                        "code": "INVALID_INVOICE",
                        "providerMessage": "Ya existe un comprobante con la misma idempotencia (uuid: 0f8fad5b-d9cb-469f-a165-70867728950e)",
                        "retryable": false,
                        "duplicate": true,
                        "uuid": "0f8fad5b-d9cb-469f-a165-70867728950e"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized. Raw shape with only a `message` key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The referenced client or service belongs to another team, or its `livemode` does\nnot match the API key. Raw shape `{ \"message\": \"Resource resolution failed\", \"error\": … }`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The referenced client or service id was not found. Raw shape.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Three cases, all raw bodies:\n\n- **Client or service lock.** A concurrent create holds the lock for the same client or service\n  (`search` + `auto_create`). `{ \"message\": \"Resource resolution failed\", \"error\": … }`. Retry\n  after about a second.\n- **`idempotency_in_progress`.** Another request with the same `idempotency_key` is being\n  processed (`IdempotencyInProgressResponse`, `retryable: true`). Retry later with the same key;\n  you get the invoice's outcome (a `400` duplicate once it exists). A request that died mid-way\n  holds the key for up to 10 minutes.\n- **`STAMP_NEEDS_REVIEW`.** An earlier attempt with this `idempotency_key` reached the PAC, and\n  the PAC could not confirm whether it stamped (no UUID returned, or the SAT's 72-hour window\n  has passed), or it stamped and the invoice could not be saved. CFDI shape under `message`,\n  `retryable: false`. Retrying could issue a second CFDI, so every retry gets this answer.\n  Contact support with the key.\n",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/LegacyErrorResponse"
                    },
                    {
                      "$ref": "#/components/schemas/IdempotencyInProgressResponse"
                    },
                    {
                      "type": "object",
                      "required": [
                        "message"
                      ],
                      "properties": {
                        "message": {
                          "$ref": "#/components/schemas/CfdiErrorResponse"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "client_lock": {
                    "summary": "Concurrent create of the same client",
                    "value": {
                      "message": "Resource resolution failed",
                      "error": "Client creation in progress for tax_id=EKU9003173C9. Please retry."
                    }
                  },
                  "idempotency_in_progress": {
                    "summary": "Same idempotency_key, still being processed",
                    "value": {
                      "message": "An invoice with this idempotency_key is already being created",
                      "error": {
                        "code": "idempotency_in_progress",
                        "message": "An invoice with this idempotency_key is already being created; retry later"
                      },
                      "retryable": true
                    }
                  },
                  "stamp_needs_review": {
                    "summary": "The PAC could not confirm an earlier attempt",
                    "value": {
                      "message": {
                        "error": "El PAC indica que el comprobante A-1284 ya fue timbrado pero no devolvió su UUID: Comprobante timbrado previamente [pcs_3b7e9d]",
                        "code": "STAMP_NEEDS_REVIEW",
                        "retryable": false
                      }
                    }
                  }
                }
              }
            }
          },
          "412": {
            "description": "**SAT not connected.** The team has no valid CSD, or the certificate failed\nvalidation. Returned in the CFDI error shape nested under `message`, with\n`retryable: false`. Upload a CSD via `POST /v2/teams/{id}/sat-connection`\nbefore retrying — retrying as-is will fail identically.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "$ref": "#/components/schemas/CfdiErrorResponse"
                    }
                  }
                },
                "example": {
                  "message": {
                    "error": "El certificado de sello digital (CSD) no está configurado o no es válido.",
                    "code": "CSD_VALIDATION_ERROR",
                    "retryable": false
                  }
                }
              }
            }
          },
          "429": {
            "description": "**Team credit limit reached.** Raw shape carrying the limit and current usage.\nNo document is created.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditLimitResponse"
                },
                "example": {
                  "message": "Team credit limit reached",
                  "error": "Credit limit of 100 documents reached for this billing period",
                  "credit_limit": 100,
                  "used_credits": 100
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error. Raw shape — either\n`{ \"message\": \"Failed to save invoice\", \"error\": { \"code\": \"invoice_save_error\", … } }`\nor `{ \"message\": \"An error occurred while creating invoice\", \"error\": { \"code\": …, \"message\": … } }`.\nA `Failed to save invoice` after a stamp means the CFDI exists: with an `idempotency_key`, a retry\nanswers `409` `STAMP_NEEDS_REVIEW` instead of stamping again.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "The stamp did not complete. CFDI error shape nested under `message`. Read `code`:\n\n- **`PAC_UNAVAILABLE`** (`retryable: true`). The PAC could not be reached, or refused the request\n  before stamping (HTTP 4xx such as 429, maintenance). The document never reached the SAT and no\n  CFDI exists. Wait a few minutes and retry.\n- **`PAC_OUTCOME_UNKNOWN`**. The request reached the PAC and its answer was lost (timeout, reset,\n  HTTP 5xx, unreadable body), so the CFDI **may exist**. Its folio is never reused.\n  - With an `idempotency_key`, `retryable: true`: retry with the **same** key. The same XML and\n    folio are sent again, so the PAC either stamps it now or returns the stamp it already made; it\n    cannot stamp twice, and the retry is not charged again. Any other failure after the XML was\n    sent is also answered this way.\n  - Without one, `retryable: false`: a new request would take a new folio and could issue a second\n    CFDI. Check whether the invoice exists before sending it again.\n\nTimeouts and HTTP 5xx from the PAC used to be answered as `PAC_UNAVAILABLE`; they are now\n`PAC_OUTCOME_UNKNOWN`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "$ref": "#/components/schemas/CfdiErrorResponse"
                    }
                  }
                },
                "examples": {
                  "pac_unavailable": {
                    "summary": "PAC unreachable; nothing was stamped",
                    "value": {
                      "message": {
                        "error": "El servicio de timbrado no está disponible en este momento. Vuelve a intentarlo en unos minutos. No se pudo contactar al PAC (Prodigia): connect ECONNREFUSED [pcs_1a2b3c]",
                        "code": "PAC_UNAVAILABLE",
                        "retryable": true
                      }
                    }
                  },
                  "pac_outcome_unknown": {
                    "summary": "PAC answer lost; retry with the same idempotency_key",
                    "value": {
                      "message": {
                        "error": "No se recibió la respuesta del servicio de timbrado; el comprobante podría estar timbrado. Se perdió la respuesta del PAC (Prodigia): The operation was aborted due to timeout [pcs_4d5e6f]",
                        "code": "PAC_OUTCOME_UNKNOWN",
                        "retryable": true
                      }
                    }
                  },
                  "pac_outcome_unknown_no_key": {
                    "summary": "PAC answer lost on a request without idempotency_key",
                    "value": {
                      "message": {
                        "error": "No se recibió la respuesta del servicio de timbrado; el comprobante podría estar timbrado. El PAC (Prodigia) respondió 504 Gateway Timeout [pcs_7a8b9c]",
                        "code": "PAC_OUTCOME_UNKNOWN",
                        "retryable": false
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/invoices/income/batch": {
      "post": {
        "operationId": "createIncomeInvoiceBatch",
        "tags": [
          "Invoices"
        ],
        "summary": "Create a batch of income invoices",
        "description": "Accepts up to **1,000** income invoices in one request and stamps them in the background. Each item is\nexactly the body of `POST /invoices/income`, and must carry its own `idempotency_key`, unique within the\nbatch. To send more than 1,000 invoices, send more batches, each with its own `Idempotency-Key`.\n\n**What happens in the request.** Every item is validated against the `POST /invoices/income` body schema,\nwith no I/O. An invalid item is listed in `rejected` with its reason and the rest go ahead; only an empty\nor missing `invoices` array, or more than 1,000 items, refuses the whole request (`400`). The answer is\n`202` with the batch in `processing`; the first items may already have started.\n\n**What happens after.** Each accepted item is stamped by the same code as `POST /invoices/income`, with\nthe credential that created the batch, so it fails for the same reasons (a client that doesn't exist, a\nSAT rejection, the credit limit) and consumes one credit when stamped. A temporary failure (PAC\nunavailable, its answer lost) is retried automatically, up to 6 attempts per item. Items run about 10 at\na time per team. Follow the batch with `GET /invoices/income/batch/{id}`, or subscribe a webhook to\n`invoice_batch.completed` (body `InvoiceBatchCompletedWebhookEvent`, signed, sent once and never\nretried; see the `webhookEvent` callback of `POST /webhooks`), then read the per-item results with\n`GET /invoices/income/batch/{id}/items`.\n\n**Two levels of idempotency.**\n- The `Idempotency-Key` header names the **batch**. The batch id is derived from your team, the\n  credential's mode and the header, so the same key with the same body returns the same batch (`200`),\n  and nothing is created again. The same key with a different body is `409` `idempotency_key_reused`.\n  Bodies are compared as sent, including key order, so resend the exact same JSON.\n- Each item's `idempotency_key` names the **invoice**. It is the same key `POST /invoices/income` uses:\n  an invoice already issued under it, by an earlier batch or a single call, is not issued again, and the\n  item ends `duplicate`. So a new batch that repeats items of a previous one is safe.\n\n**gigstack Connect:** create the batch for a connected team with the `team` parameter, and read it with the\nsame `team`.\n\n**Mode.** `livemode` comes only from the credential: a test key creates a test batch.\n\nNot supported here: file uploads (CSV/XLSX), egress invoices and payment complements. If most of your\nsales are to the general public, the monthly global invoice (*factura global*) that gigstack already\nproduces may be all you need.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Your identifier for this batch, 8-128 characters of `A-Z a-z 0-9 . _ : -`. Reusing it with the same\nbody returns the batch it first created; reusing it with a different body is `409 idempotency_key_reused`.\n",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]{8,128}$"
            },
            "example": "sales-2026-09-29-part-1"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceBatchCreateInput"
              },
              "example": {
                "invoices": [
                  {
                    "idempotency_key": "order-2026-09-000123",
                    "automation_type": "none",
                    "currency": "MXN",
                    "use": "G03",
                    "payment_form": "04",
                    "payment_method": "PUE",
                    "client": {
                      "id": "client_1234567890"
                    },
                    "items": [
                      {
                        "description": "Professional consulting services",
                        "product_key": "80141503",
                        "unit_key": "E48",
                        "unit_price": 1000,
                        "quantity": 1,
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false
                          }
                        ]
                      }
                    ],
                    "send_email": true
                  },
                  {
                    "idempotency_key": "order-2026-09-000124",
                    "automation_type": "none",
                    "currency": "MXN",
                    "use": "G03",
                    "payment_form": "03",
                    "payment_method": "PUE",
                    "client": {
                      "id": "client_0987654321"
                    },
                    "items": [
                      {
                        "description": "Annual support plan",
                        "product_key": "81111811",
                        "unit_key": "E48",
                        "unit_price": 2500,
                        "quantity": 1,
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Retry of an earlier request with the same `Idempotency-Key` and the same body: the batch it created,\nas it is now. Nothing is created again. If the first request died while writing the batch, this\nrequest finishes creating it.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicInvoiceBatch"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "ibatch_5d41402abc4b2a76b9719d911017c592",
                    "object": "invoice_batch",
                    "type": "income",
                    "livemode": true,
                    "status": "processing",
                    "result": null,
                    "total": 250,
                    "accepted": 248,
                    "rejected": [
                      {
                        "index": 17,
                        "idempotency_key": "order-2026-09-000140",
                        "error": {
                          "code": "invalid_body",
                          "message": "client_id: Unexpected field"
                        }
                      },
                      {
                        "index": 42,
                        "idempotency_key": "order-2026-09-000123",
                        "error": {
                          "code": "duplicate_idempotency_key",
                          "message": "idempotency_key is already used by item 0"
                        }
                      }
                    ],
                    "counts": {
                      "queued": 131,
                      "stamped": 115,
                      "failed": 1,
                      "duplicate": 1,
                      "needs_review": 0
                    },
                    "created_at": 1790780400000,
                    "completed_at": null
                  },
                  "timestamp": 1790781000000
                }
              }
            }
          },
          "202": {
            "description": "Batch created. `status` is `processing`; the accepted items are being stamped in the background.\nItems refused by validation are in `rejected` and will not be stamped. A batch in which every item\nwas rejected has nothing to stamp and is usually already `completed`, with `result: failed`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicInvoiceBatch"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "ibatch_5d41402abc4b2a76b9719d911017c592",
                    "object": "invoice_batch",
                    "type": "income",
                    "livemode": true,
                    "status": "processing",
                    "result": null,
                    "total": 250,
                    "accepted": 248,
                    "rejected": [
                      {
                        "index": 17,
                        "idempotency_key": "order-2026-09-000140",
                        "error": {
                          "code": "invalid_body",
                          "message": "client_id: Unexpected field"
                        }
                      },
                      {
                        "index": 42,
                        "idempotency_key": "order-2026-09-000123",
                        "error": {
                          "code": "duplicate_idempotency_key",
                          "message": "idempotency_key is already used by item 0"
                        }
                      }
                    ],
                    "counts": {
                      "queued": 248,
                      "stamped": 0,
                      "failed": 0,
                      "duplicate": 0,
                      "needs_review": 0
                    },
                    "created_at": 1790780400000,
                    "completed_at": null
                  },
                  "timestamp": 1790780401250
                }
              }
            }
          },
          "400": {
            "description": "The request was refused and no batch was created. `error.code`:\n\n- `invalid_request_body`: the `Idempotency-Key` header is missing or malformed.\n- `invalid_body`: the body is not `{ \"invoices\": [ … ] }` with at least one item.\n- `too_many_items`: more than 1,000 items. Split them into several batches.\n\nProblems with a single item don't refuse the request; they are listed in the batch's `rejected`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "examples": {
                  "missing_idempotency_key": {
                    "summary": "Idempotency-Key header missing",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Idempotency-Key header is required"
                      },
                      "timestamp": 1790780400000
                    }
                  },
                  "malformed_idempotency_key": {
                    "summary": "Idempotency-Key does not match the format",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Idempotency-Key must be 8-128 chars matching [A-Za-z0-9._:-]"
                      },
                      "timestamp": 1790780400000
                    }
                  },
                  "invalid_body": {
                    "summary": "No invoices array",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_body",
                        "message": "Body must be { \"invoices\": [ ... ] } with at least one invoice"
                      },
                      "timestamp": 1790780400000
                    }
                  },
                  "too_many_items": {
                    "summary": "More than 1,000 invoices",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "too_many_items",
                        "message": "A batch holds at most 1000 invoices; send the rest in more batches"
                      },
                      "timestamp": 1790780400000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Either the authentication layer refused the credential (raw body, see `AuthForbidden`), or a\nuser-scoped token (MCP, dashboard) lacks `editor` permission on invoices (standardized envelope,\n`forbidden`). API keys and OAuth tokens act as the team and are not role-checked.\n",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/StandardErrorResponse"
                    },
                    {
                      "$ref": "#/components/schemas/AuthMiddlewareError"
                    }
                  ]
                },
                "examples": {
                  "missing_invoices_permission": {
                    "summary": "User-scoped token without editor permission on invoices",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "forbidden",
                        "message": "This action requires editor access to invoices"
                      },
                      "timestamp": 1790780400000
                    }
                  },
                  "revoked_api_key": {
                    "summary": "Authentication layer - API key revoked or disabled",
                    "value": {
                      "message": "API Key inválida.",
                      "details": "Invalid API Key"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: the `Idempotency-Key` was already used with a **different body**. Nothing\nwas created. Send the new body under a new key; to read the original batch, use\n`GET /invoices/income/batch/{id}`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "idempotency_key_reused",
                    "message": "This Idempotency-Key was already used with a different body. Use a new key for a different batch."
                  },
                  "timestamp": 1790780400000
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (`internal_server_error`). Retrying with the **same** `Idempotency-Key` and body\nis safe: it returns the batch if it was created, or creates it.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "internal_server_error",
                    "message": "An internal server error occurred"
                  },
                  "timestamp": 1790780400000
                }
              }
            }
          }
        }
      }
    },
    "/invoices/income/batch/{id}": {
      "get": {
        "operationId": "getIncomeInvoiceBatch",
        "tags": [
          "Invoices"
        ],
        "summary": "Get an income invoice batch",
        "description": "Returns the batch: the items rejected up front, and the progress of the accepted ones in `counts`. Poll it\nuntil `status` is `completed`, then read `result`, not `status`, to know how it went: `completed`\n(everything issued), `partially_completed` (some items have no invoice) or `failed` (none issued).\n\nFor each invoice's outcome, page through `GET /invoices/income/batch/{id}/items`.\n\nA batch of another team, or of the other mode (a live batch read with a test key), answers `404`.\nUnder gigstack Connect, send the same `team` the batch was created with.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Batch id, as returned by `POST /invoices/income/batch`.",
            "schema": {
              "type": "string"
            },
            "example": "ibatch_5d41402abc4b2a76b9719d911017c592"
          }
        ],
        "responses": {
          "200": {
            "description": "The batch.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicInvoiceBatch"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "processing": {
                    "summary": "Still stamping",
                    "value": {
                      "success": true,
                      "data": {
                        "id": "ibatch_5d41402abc4b2a76b9719d911017c592",
                        "object": "invoice_batch",
                        "type": "income",
                        "livemode": true,
                        "status": "processing",
                        "result": null,
                        "total": 250,
                        "accepted": 248,
                        "rejected": [
                          {
                            "index": 17,
                            "idempotency_key": "order-2026-09-000140",
                            "error": {
                              "code": "invalid_body",
                              "message": "client_id: Unexpected field"
                            }
                          },
                          {
                            "index": 42,
                            "idempotency_key": "order-2026-09-000123",
                            "error": {
                              "code": "duplicate_idempotency_key",
                              "message": "idempotency_key is already used by item 0"
                            }
                          }
                        ],
                        "counts": {
                          "queued": 131,
                          "stamped": 115,
                          "failed": 1,
                          "duplicate": 1,
                          "needs_review": 0
                        },
                        "created_at": 1790780400000,
                        "completed_at": null
                      },
                      "timestamp": 1790781000000
                    }
                  },
                  "partially_completed": {
                    "summary": "Finished, some items have no invoice",
                    "value": {
                      "success": true,
                      "data": {
                        "id": "ibatch_5d41402abc4b2a76b9719d911017c592",
                        "object": "invoice_batch",
                        "type": "income",
                        "livemode": true,
                        "status": "completed",
                        "result": "partially_completed",
                        "total": 250,
                        "accepted": 248,
                        "rejected": [
                          {
                            "index": 17,
                            "idempotency_key": "order-2026-09-000140",
                            "error": {
                              "code": "invalid_body",
                              "message": "client_id: Unexpected field"
                            }
                          },
                          {
                            "index": 42,
                            "idempotency_key": "order-2026-09-000123",
                            "error": {
                              "code": "duplicate_idempotency_key",
                              "message": "idempotency_key is already used by item 0"
                            }
                          }
                        ],
                        "counts": {
                          "queued": 0,
                          "stamped": 245,
                          "failed": 2,
                          "duplicate": 1,
                          "needs_review": 0
                        },
                        "created_at": 1790780400000,
                        "completed_at": 1790784000000
                      },
                      "timestamp": 1790784060000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "No batch with this id in your team and mode (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "not_found",
                    "message": "Invoice batch not found"
                  },
                  "timestamp": 1790781000000
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/income/batch/{id}/items": {
      "get": {
        "operationId": "listIncomeInvoiceBatchItems",
        "tags": [
          "Invoices"
        ],
        "summary": "List the items of an income invoice batch",
        "description": "One entry per **accepted** item, in request order (ascending `index`), with its status and, once issued,\nits invoice. Items rejected up front are not listed; they are in the batch's `rejected`.\n\nCursor pagination: pass `data.next` back as `next` while `data.has_more` is `true`. The cursor is the last\n`index` of the page, so pages never overlap or skip items while statuses change. Filter with `status`,\nfor example `status=failed` to list only what needs fixing.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Batch id.",
            "schema": {
              "type": "string"
            },
            "example": "ibatch_5d41402abc4b2a76b9719d911017c592"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per page (default **100**, 1-500). Anything else is `400 invalid_limit`.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "example": 100
          },
          {
            "name": "next",
            "in": "query",
            "required": false,
            "description": "Cursor from the previous page's `data.next`. Omit for the first page. An invalid one is `400 invalid_cursor`.",
            "schema": {
              "type": "string"
            },
            "example": "99"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only items in this status. `queued` covers every item still in flight. Any other value is\n`400 invalid_status`. Omit for all items.\n",
            "schema": {
              "$ref": "#/components/schemas/InvoiceBatchItemStatusEnum"
            },
            "example": "failed"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of items. Note the nesting: the array is at `data.data`, the cursor at `data.next`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicInvoiceBatchItemsPage"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "data": [
                      {
                        "index": 0,
                        "idempotency_key": "order-2026-09-000123",
                        "status": "stamped",
                        "invoice_id": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                        "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                        "error": null,
                        "attempts": 1
                      },
                      {
                        "index": 1,
                        "idempotency_key": "order-2026-09-000124",
                        "status": "duplicate",
                        "invoice_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
                        "uuid": "0f8fad5b-d9cb-469f-a165-70867728950e",
                        "error": null,
                        "attempts": 1
                      },
                      {
                        "index": 2,
                        "idempotency_key": "order-2026-09-000125",
                        "status": "failed",
                        "invoice_id": null,
                        "uuid": null,
                        "error": {
                          "code": "CFDI40147",
                          "message": "Error al timbrar la factura: CFDI40147 - El campo UsoCFDI no es válido [pcs_8f2a1c]"
                        },
                        "attempts": 1
                      },
                      {
                        "index": 3,
                        "idempotency_key": "order-2026-09-000126",
                        "status": "queued",
                        "invoice_id": null,
                        "uuid": null,
                        "error": null,
                        "attempts": 2
                      }
                    ],
                    "next": "3",
                    "has_more": true
                  },
                  "timestamp": 1790781000000
                }
              }
            }
          },
          "400": {
            "description": "A query parameter is invalid. `error.code`: `invalid_limit`, `invalid_status` or `invalid_cursor`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "examples": {
                  "invalid_limit": {
                    "summary": "limit out of range",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_limit",
                        "message": "limit must be an integer between 1 and 500"
                      },
                      "timestamp": 1790781000000
                    }
                  },
                  "invalid_status": {
                    "summary": "Unknown status filter",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_status",
                        "message": "status must be one of queued, stamped, failed, duplicate, needs_review"
                      },
                      "timestamp": 1790781000000
                    }
                  },
                  "invalid_cursor": {
                    "summary": "Malformed cursor",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_cursor",
                        "message": "next is not a valid cursor"
                      },
                      "timestamp": 1790781000000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "No batch with this id in your team and mode (`not_found`). Checked before the query parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "not_found",
                    "message": "Invoice batch not found"
                  },
                  "timestamp": 1790781000000
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/income/{id}": {
      "get": {
        "operationId": "getInvoicesIncomeById",
        "tags": [
          "Invoices"
        ],
        "summary": "Get income invoice",
        "description": "Retrieve a specific income invoice by ID.\n\n**gigstack Connect:** Access other teams' invoices using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "SAT UUID (folio fiscal)",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          }
        ],
        "responses": {
          "200": {
            "description": "Invoice retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Invoice retrieved successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicIncomeInvoice"
                    }
                  }
                },
                "example": {
                  "message": "Invoice retrieved successfully",
                  "data": {
                    "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                    "client": {
                      "id": "client_1234567890",
                      "name": "Juan Pérez García",
                      "email": "juan.perez@ejemplo.com",
                      "tax_id": "PEGJ800101ABC",
                      "from": "api",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "status": "valid",
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "total": 1160,
                    "subtotal": 1000,
                    "taxes": 160,
                    "discount": 0,
                    "series": "A",
                    "folio_number": 123,
                    "invoice_type": "I",
                    "payment_method": "PUE",
                    "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx",
                    "created_at": 1677651234,
                    "livemode": true,
                    "owner": "user_1234567890"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/egress": {
      "get": {
        "operationId": "getInvoicesEgress",
        "tags": [
          "Invoices"
        ],
        "summary": "List egress invoices",
        "description": "Retrieve a paginated list of egress invoices with powerful filtering capabilities.\n\n**gigstack Connect:** Access other teams' invoices using the `team` parameter.\n\n**Filtering Options:**\n- Filter by creation date using comparison operators\n- Filter by `status`, `series`, `folio` and `idempotency_key` (exact match only)\n- Filter by metadata fields using dot or underscore notation (e.g., `metadata.order_id` or `metadata_order_id`)\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "$ref": "#/components/parameters/ClientIdFilterParam"
          },
          {
            "$ref": "#/components/parameters/TaxIdFilterParam"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by invoice status. `cancelled` is accepted as an alias of `canceled`.\n",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "valid",
                "canceled",
                "cancelled"
              ]
            }
          },
          {
            "name": "series",
            "in": "query",
            "description": "Filter by exact invoice series (no prefix matching).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "folio",
            "in": "query",
            "description": "Filter by exact folio number (no prefix matching).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "idempotency_key",
            "in": "query",
            "description": "Filter by the exact idempotency key the invoice was created with.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "metadata.{key}",
            "in": "query",
            "description": "Filter by any metadata field using dot notation (e.g., `metadata.order_id=ORD-123`)\nor underscore notation (e.g., `metadata_order_id=ORD-123`).\nBoth formats are supported and equivalent.\nUses Typesense search for efficient querying without requiring Firestore indexes.\n",
            "required": false,
            "schema": {
              "type": "string"
            },
            "style": "form"
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination when using metadata filters (default 1).\nOnly applies when filtering by metadata fields.\n",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invoices retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                },
                "example": {
                  "success": true,
                  "message": "Invoices retrieved successfully",
                  "data": [
                    {
                      "uuid": "C1D2E3F4-2B3C-4D5E-8F9A-1234567890BC",
                      "idempotency_key": null,
                      "client": {
                        "id": "client_1234567890",
                        "name": "ESCUELA KEMPER URGATE",
                        "legal_name": "ESCUELA KEMPER URGATE",
                        "email": "contabilidad@ejemplo.com",
                        "bcc": [],
                        "phone": "+524421234567",
                        "tax_id": "EKU9003173C9",
                        "tax_system": "601",
                        "use": "G03",
                        "address": {
                          "street": "Av. Constituyentes",
                          "exterior": "1000",
                          "neighborhood": "Centro",
                          "city": "Querétaro",
                          "state": "QRO",
                          "zip": "76000",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "efos": {
                          "is_valid": true
                        },
                        "metadata": {},
                        "livemode": true,
                        "from": "api",
                        "owner": "user_1234567890",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      },
                      "created_at": 1767225600000,
                      "date": 1767225600000,
                      "currency": "MXN",
                      "exchange_rate": 1,
                      "total": 580,
                      "subtotal": 500,
                      "discount": 0,
                      "taxes": 80,
                      "withholding_taxes": 0,
                      "series": "NC",
                      "folio_number": 12,
                      "invoice_type": "E",
                      "use": "G02",
                      "payment_form": "03",
                      "payment_method": "PUE",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "from": "api",
                      "status": "valid",
                      "payments": [],
                      "invoices": [],
                      "items": [
                        {
                          "id": "item_nc_001",
                          "description": "Bonificación por ajuste de servicio",
                          "quantity": 1,
                          "unit_price": 500,
                          "product_key": "84111506",
                          "unit_key": "ACT"
                        }
                      ],
                      "metadata": {},
                      "emails": [
                        "contabilidad@ejemplo.com"
                      ],
                      "cancellation": null,
                      "stamp": {
                        "sello": "kQ3xZ9vR2mP7tL4wN8cB1yH6",
                        "stamp_at": 1767225600000
                      },
                      "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=C1D2E3F4-2B3C-4D5E-8F9A-1234567890BC&re=MEE200101ABC&rr=EKU9003173C9&tt=580.00&fe=kQ3xZ9",
                      "related_documents": [
                        {
                          "relationship": "01",
                          "documents": [
                            "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
                          ]
                        }
                      ]
                    }
                  ],
                  "next": null,
                  "has_more": false,
                  "total_results": 1,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createInvoicesEgress",
        "tags": [
          "Invoices"
        ],
        "summary": "Create egress invoice",
        "description": "[Small working example](/recipes/credit-note)\n\n**Integration note:** A credit note adjusts the fiscal document. It does not refund money through a payment processor. Verified staging issuance returned HTTP 200 and data.uuid. Read [shared fields](/concepts/shared-fields) and the [Mexico](/countries/mexico) or [Colombia](/countries/colombia) guide for country-specific meaning. The linked fiscal recipes and staging issuance results use a Mexican issuer.\n\nCreate a new egress invoice (expense/credit note) with CFDI 4.0 compliance.\n\n**gigstack Connect:** Create invoices for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceEgressInput"
              },
              "example": {
                "automation_type": "none",
                "currency": "MXN",
                "use": "G03",
                "payment_form": "03",
                "client": {
                  "id": "client_1234567890"
                },
                "items": [
                  {
                    "quantity": 1,
                    "description": "Purchased materials",
                    "sku": "MAT-001",
                    "product_key": "80141503",
                    "unit_key": "E48",
                    "unit_name": "Unidad",
                    "unit_price": 500,
                    "taxability": "02",
                    "taxes": [
                      {
                        "type": "IVA",
                        "rate": 0.16,
                        "factor": "Tasa",
                        "withholding": false,
                        "inclusive": false
                      }
                    ]
                  }
                ],
                "send_email": true,
                "emails": [
                  "proveedor@empresa.com"
                ],
                "metadata": {
                  "purchase_order": "PO-2024-001",
                  "department": "procurement"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Invoice created successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicIncomeInvoice"
                    }
                  }
                },
                "example": {
                  "message": "Invoice created successfully",
                  "data": {
                    "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                    "client": {
                      "id": "client_1234567890",
                      "name": "Proveedor ABC SA",
                      "email": "proveedor@empresa.com",
                      "tax_id": "PABC800101ABC",
                      "from": "api",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "status": "valid",
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "total": 580,
                    "subtotal": 500,
                    "taxes": 80,
                    "discount": 0,
                    "series": "E",
                    "folio_number": 123,
                    "invoice_type": "E",
                    "items": [
                      {
                        "id": "item_1234567890",
                        "description": "Purchased materials",
                        "quantity": 1,
                        "unit_price": 500,
                        "product_key": "80141503",
                        "unit_key": "E48"
                      }
                    ],
                    "created_at": 1677651234,
                    "livemode": true,
                    "owner": "user_1234567890"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request. All bodies here are **raw**, not the standardized envelope.\n- Body validation: `{ \"message\": \"Invalid body\", \"errors\": [ { \"path\": …, \"code\": …, \"message\": … } ] }`.\n  Unknown keys are rejected — there is no `client_id` field; use `client: { \"id\": … }`.\n- `{ \"message\": \"Billing account not found\", \"error\": \"Billing account is required\" }`\n- `{ \"message\": \"Invalid currency\", \"error\": … }`\n- `{ \"message\": \"Exchange rate not found\" }`\n- `{ \"message\": \"Resource resolution failed\", \"error\": … }` when the client/service\n  reference is ambiguous (both `id` and `search`, or `safety_check` matched several).\n- Generic CFDI/PAC stamping failure, nested one level under `message`:\n  `{ \"message\": { \"error\": …, \"code\": …, \"providerMessage\": …, \"retryable\": false } }`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LegacyErrorResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "message": {
                          "$ref": "#/components/schemas/CfdiErrorResponse"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized. Raw shape with only a `message` key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The referenced client or service belongs to another team, or its `livemode` does\nnot match the API key. Raw shape `{ \"message\": \"Resource resolution failed\", \"error\": … }`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The referenced client or service id was not found. Raw shape.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A concurrent create holds the lock for the same client or service. Retry the\nrequest. Raw shape.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "412": {
            "description": "**SAT not connected.** The team has no valid CSD, or the certificate failed\nvalidation. Returned in the CFDI error shape nested under `message`, with\n`retryable: false`. Upload a CSD via `POST /v2/teams/{id}/sat-connection`\nbefore retrying — retrying as-is will fail identically.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "$ref": "#/components/schemas/CfdiErrorResponse"
                    }
                  }
                },
                "example": {
                  "message": {
                    "error": "El certificado de sello digital (CSD) no está configurado o no es válido.",
                    "code": "csd_validation_error",
                    "retryable": false
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error. Raw shape — either\n`{ \"message\": \"Failed to save invoice\", \"error\": { \"code\": \"invoice_save_error\", … } }`\nor `{ \"message\": \"An error occurred while creating invoice\", \"error\": { \"code\": …, \"message\": … } }`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "**PAC unavailable.** The stamping provider could not be reached. Returned in the\nCFDI error shape nested under `message`, with `retryable: true` — this is the only\nCFDI failure that is safe to retry unchanged. Wait a few minutes and retry with\nthe same `idempotency_key`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "$ref": "#/components/schemas/CfdiErrorResponse"
                    }
                  }
                },
                "example": {
                  "message": {
                    "error": "El servicio de timbrado no está disponible en este momento. Vuelve a intentarlo en unos minutos.",
                    "code": "pac_unavailable",
                    "retryable": true
                  }
                }
              }
            }
          }
        }
      }
    },
    "/invoices/egress/{id}": {
      "get": {
        "operationId": "getInvoicesEgressById",
        "tags": [
          "Invoices"
        ],
        "summary": "Get egress invoice",
        "description": "Retrieve a specific egress invoice by ID.\n\n**gigstack Connect:** Access other teams' invoices using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "SAT UUID (folio fiscal)",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          }
        ],
        "responses": {
          "200": {
            "description": "Invoice retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Invoice retrieved successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicIncomeInvoice"
                    }
                  }
                },
                "example": {
                  "message": "Invoice retrieved successfully",
                  "data": {
                    "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                    "client": {
                      "id": "client_1234567890",
                      "name": "Proveedor ABC SA",
                      "email": "proveedor@empresa.com",
                      "tax_id": "PABC800101ABC",
                      "from": "api",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "status": "valid",
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "total": 580,
                    "subtotal": 500,
                    "taxes": 80,
                    "discount": 0,
                    "series": "E",
                    "folio_number": 123,
                    "invoice_type": "E",
                    "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx",
                    "created_at": 1677651234,
                    "livemode": true,
                    "owner": "user_1234567890"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/transfer": {
      "get": {
        "operationId": "getInvoicesTransfer",
        "tags": [
          "Invoices"
        ],
        "summary": "List transfer invoices",
        "description": "Retrieve a paginated list of transfer invoices (CFDI type T - Traslado with Carta Porte).\n\n**gigstack Connect:** Access other teams' invoices using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Transfer invoices retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "postInvoicesTransfer",
        "tags": [
          "Invoices"
        ],
        "summary": "Create transfer invoice (Carta Porte)",
        "description": "Stamp a CFDI type T (traslado) with the Carta Porte 3.1 complement, for moving goods by road\n(autotransporte).\n\n- The comprobante is fixed by the SAT: `Moneda` XXX, `Total` 0, `UsoCFDI` S01, no `MetodoPago`.\n  `currency`, `use`, `payment_method` and `payment_form` are ignored if sent.\n- There are no `items`: the CFDI conceptos are built from `carta_porte.Mercancias.Mercancia`.\n- `carta_porte` uses the SAT attribute names from CartaPorte31.xsd. Numbers may be sent as\n  numbers or numeric strings.\n- At least one `Origen` and one `Destino`; every `Destino` needs `DistanciaRecorrida`.\n  `DistanciaRecorrida` is dropped from the `Origen`.\n- `FiguraTransporte` is required (for `TipoFigura` 01, the operator, send `NumLicencia`).\n- The series defaults to `T`.\n- Only teams stamping through gigstack's own PAC (CSD uploaded) can use this endpoint.\n\nStamping is irreversible. Use a test API key to try it without fiscal effect.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "client",
                  "carta_porte"
                ],
                "properties": {
                  "client": {
                    "description": "Client reference (receptor). Same format as income invoices.",
                    "type": "object"
                  },
                  "carta_porte": {
                    "type": "object",
                    "required": [
                      "TranspInternac",
                      "TotalDistRec",
                      "Ubicaciones",
                      "Mercancias",
                      "Autotransporte",
                      "FiguraTransporte"
                    ],
                    "properties": {
                      "TranspInternac": {
                        "type": "string",
                        "enum": [
                          "Sí",
                          "No"
                        ]
                      },
                      "EntradaSalidaMerc": {
                        "type": "string",
                        "enum": [
                          "Entrada",
                          "Salida"
                        ]
                      },
                      "PaisOrigenDestino": {
                        "type": "string"
                      },
                      "ViaEntradaSalida": {
                        "type": "string"
                      },
                      "TotalDistRec": {
                        "type": "number"
                      },
                      "Ubicaciones": {
                        "type": "array",
                        "minItems": 2,
                        "items": {
                          "type": "object"
                        }
                      },
                      "Mercancias": {
                        "type": "object"
                      },
                      "Autotransporte": {
                        "type": "object"
                      },
                      "FiguraTransporte": {
                        "type": "array",
                        "minItems": 1,
                        "items": {
                          "type": "object"
                        }
                      }
                    }
                  },
                  "series": {
                    "type": "string"
                  },
                  "folio_number": {
                    "type": "number"
                  },
                  "date": {
                    "type": "number",
                    "description": "Unix epoch milliseconds"
                  },
                  "idempotency_key": {
                    "type": "string"
                  },
                  "related_documents": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  },
                  "metadata": {
                    "type": "object"
                  },
                  "send_email": {
                    "type": "boolean"
                  },
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email"
                    }
                  },
                  "return_files": {
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "client": {
                  "id": "client_1234567890"
                },
                "carta_porte": {
                  "TranspInternac": "No",
                  "TotalDistRec": 120,
                  "Ubicaciones": [
                    {
                      "TipoUbicacion": "Origen",
                      "RFCRemitenteDestinatario": "EKU9003173C9",
                      "NombreRemitenteDestinatario": "ESCUELA KEMPER URGATE",
                      "FechaHoraSalidaLlegada": "2026-10-06T09:00:00",
                      "Domicilio": {
                        "Pais": "MEX",
                        "CodigoPostal": "42501",
                        "Estado": "HID"
                      }
                    },
                    {
                      "TipoUbicacion": "Destino",
                      "RFCRemitenteDestinatario": "EKU9003173C9",
                      "NombreRemitenteDestinatario": "ESCUELA KEMPER URGATE",
                      "FechaHoraSalidaLlegada": "2026-10-06T13:00:00",
                      "DistanciaRecorrida": 120,
                      "Domicilio": {
                        "Pais": "MEX",
                        "CodigoPostal": "03020",
                        "Estado": "CMX"
                      }
                    }
                  ],
                  "Mercancias": {
                    "PesoBrutoTotal": 12.5,
                    "UnidadPeso": "KGM",
                    "NumTotalMercancias": 1,
                    "Mercancia": [
                      {
                        "BienesTransp": "50202203",
                        "Descripcion": "Bebida embotellada",
                        "Cantidad": 10,
                        "ClaveUnidad": "XBO",
                        "PesoEnKg": 12.5
                      }
                    ]
                  },
                  "Autotransporte": {
                    "PermSCT": "TPAF01",
                    "NumPermisoSCT": "0X2XTXZ0X5X0X3X2X1X0",
                    "IdentificacionVehicular": {
                      "ConfigVehicular": "VL",
                      "PlacaVM": "ABC1234",
                      "AnioModeloVM": 2022,
                      "PesoBrutoVehicular": 3
                    },
                    "Seguros": {
                      "AseguraRespCivil": "SEGUROS SA",
                      "PolizaRespCivil": "123456"
                    }
                  },
                  "FiguraTransporte": [
                    {
                      "TipoFigura": "01",
                      "RFCFigura": "VAAM130719H60",
                      "NombreFigura": "OPERADOR",
                      "NumLicencia": "a234567890"
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transfer invoice stamped",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Transfer invoice created"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid body or Carta Porte rule (e.g. missing DistanciaRecorrida on a Destino)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/transfer/{id}": {
      "get": {
        "operationId": "getInvoicesTransferById",
        "tags": [
          "Invoices"
        ],
        "summary": "Get transfer invoice",
        "description": "Retrieve a specific transfer invoice by ID (CFDI type T - Traslado).",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Transfer invoice retrieved successfully"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Invoice not found"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/payment": {
      "get": {
        "operationId": "getInvoicesPayment",
        "tags": [
          "Invoices"
        ],
        "summary": "List payment complement invoices",
        "description": "Retrieve a paginated list of payment complement invoices (CFDI type P - Complemento de Pago).\n\nPayment complements are used for PPD (Pago en Parcialidades o Diferido) invoices to register partial or deferred payments.\n\n**gigstack Connect:** Access other teams' invoices using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "name": "idempotency_key",
            "in": "query",
            "description": "Filter by the exact idempotency key the payment complement was created with.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Payment complement invoices retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                },
                "example": {
                  "success": true,
                  "message": "Invoices retrieved successfully",
                  "data": [
                    {
                      "uuid": "D2E3F4A5-3C4D-4E5F-9A0B-234567890CDE",
                      "idempotency_key": null,
                      "client": {
                        "id": "client_1234567890",
                        "name": "ESCUELA KEMPER URGATE",
                        "legal_name": "ESCUELA KEMPER URGATE",
                        "email": "contabilidad@ejemplo.com",
                        "bcc": [],
                        "phone": "+524421234567",
                        "tax_id": "EKU9003173C9",
                        "tax_system": "601",
                        "use": "G03",
                        "address": {
                          "street": "Av. Constituyentes",
                          "exterior": "1000",
                          "neighborhood": "Centro",
                          "city": "Querétaro",
                          "state": "QRO",
                          "zip": "76000",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "efos": {
                          "is_valid": true
                        },
                        "metadata": {},
                        "livemode": true,
                        "from": "api",
                        "owner": "user_1234567890",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      },
                      "created_at": 1767225600000,
                      "date": 1767225600000,
                      "currency": "XXX",
                      "exchange_rate": 1,
                      "total": 0,
                      "subtotal": 0,
                      "discount": 0,
                      "taxes": 0,
                      "withholding_taxes": 0,
                      "series": "P",
                      "folio_number": 45,
                      "invoice_type": "P",
                      "use": "CP01",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "from": "api",
                      "status": "valid",
                      "payments": [],
                      "invoices": [],
                      "items": [
                        {
                          "id": "item_pago",
                          "description": "Pago",
                          "quantity": 1,
                          "unit_price": 0,
                          "product_key": "84111506",
                          "unit_key": "ACT"
                        }
                      ],
                      "metadata": {},
                      "emails": [
                        "contabilidad@ejemplo.com"
                      ],
                      "cancellation": null,
                      "stamp": {
                        "sello": "kQ3xZ9vR2mP7tL4wN8cB1yH6",
                        "stamp_at": 1767225600000
                      },
                      "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=D2E3F4A5-3C4D-4E5F-9A0B-234567890CDE&re=MEE200101ABC&rr=EKU9003173C9&tt=0.00&fe=kQ3xZ9",
                      "related_documents": []
                    }
                  ],
                  "next": null,
                  "has_more": false,
                  "total_results": 1,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createInvoicesPayment",
        "tags": [
          "Invoices"
        ],
        "summary": "Create payment complement (complemento de pago)",
        "description": "Stamp a CFDI type \"P\" payment complement (complemento de pago, Pagos 2.0) that\nregisters one or more payments against PPD (Pago en Parcialidades o Diferido) invoices.\n\nEach entry in `complements[].data` is a payment. Each payment links one or more PPD\ninvoices through `related_documents`, supplying the amount paid, the installment number\nand the previous balance so the SAT can compute the remaining balance.\n\n**Fixed by the SAT** and therefore not required in the body: the comprobante currency\n(`XXX`), the receptor `UsoCFDI` (`CP01`), and the line concept. The per-payment currency\nlives in each payment's `currency` field. The series defaults to the team's payments\nseries (`invoice_serie_payments`).\n\n**gigstack Connect:** Create for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PaymentComplementInput"
              },
              "example": {
                "client": {
                  "id": "client_1234567890"
                },
                "date": 1784915988000,
                "complements": [
                  {
                    "type": "pago",
                    "data": [
                      {
                        "payment_form": "03",
                        "date": "2026-07-24T12:00:00",
                        "currency": "MXN",
                        "exchange": 1,
                        "related_documents": [
                          {
                            "uuid": "A1B2C3D4-E5F6-7890-ABCD-1234567890AB",
                            "amount": 116,
                            "installment": 1,
                            "last_balance": 116,
                            "currency": "MXN",
                            "taxes": [
                              {
                                "base": 100,
                                "rate": "0.16",
                                "factor": "Tasa",
                                "type": "IVA",
                                "withholding": false,
                                "inclusive": false
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ],
                "return_files": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment complement created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Payment complement created"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicIncomeInvoice"
                    }
                  }
                },
                "example": {
                  "message": "Payment complement created",
                  "data": {
                    "uuid": "D2E3F4A5-3C4D-4E5F-9A0B-234567890CDE",
                    "idempotency_key": null,
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "created_at": 1767225600000,
                    "date": 1767225600000,
                    "currency": "XXX",
                    "exchange_rate": 1,
                    "total": 0,
                    "subtotal": 0,
                    "discount": 0,
                    "taxes": 0,
                    "withholding_taxes": 0,
                    "series": "P",
                    "folio_number": 45,
                    "invoice_type": "P",
                    "use": "CP01",
                    "livemode": true,
                    "owner": "user_1234567890",
                    "team": "team_1234567890",
                    "from": "api",
                    "status": "valid",
                    "payments": [],
                    "invoices": [],
                    "items": [
                      {
                        "id": "item_pago",
                        "description": "Pago",
                        "quantity": 1,
                        "unit_price": 0,
                        "product_key": "84111506",
                        "unit_key": "ACT"
                      }
                    ],
                    "metadata": {},
                    "emails": [
                      "contabilidad@ejemplo.com"
                    ],
                    "cancellation": null,
                    "stamp": {
                      "sello": "kQ3xZ9vR2mP7tL4wN8cB1yH6",
                      "stamp_at": 1767225600000
                    },
                    "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=D2E3F4A5-3C4D-4E5F-9A0B-234567890CDE&re=MEE200101ABC&rr=EKU9003173C9&tt=0.00&fe=kQ3xZ9",
                    "related_documents": []
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/payment/{id}": {
      "get": {
        "operationId": "getInvoicesPaymentById",
        "tags": [
          "Invoices"
        ],
        "summary": "Get payment complement invoice",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nRetrieve a specific payment complement invoice by ID (CFDI type P - Complemento de Pago).\n\nPayment complements contain details about payments made against PPD invoices, including:\n- Payment amounts and dates\n- Payment method and form\n- Related PPD invoices\n- Tax calculations on payments\n\n**gigstack Connect:** Access other teams' invoices using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "SAT UUID (folio fiscal)",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment complement invoice retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Invoice retrieved successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicIncomeInvoice"
                    }
                  }
                },
                "example": {
                  "message": "Invoice retrieved successfully",
                  "data": {
                    "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                    "client": {
                      "id": "client_1234567890",
                      "name": "Juan Pérez García",
                      "email": "juan.perez@example.com",
                      "tax_id": "PEGJ800101ABC",
                      "from": "api",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "status": "valid",
                    "currency": "XXX",
                    "exchange_rate": 1,
                    "total": 0,
                    "subtotal": 0,
                    "taxes": 0,
                    "discount": 0,
                    "series": "CP",
                    "folio_number": 456,
                    "invoice_type": "P",
                    "payment_method": "PPD",
                    "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx",
                    "created_at": 1677651234,
                    "livemode": true,
                    "owner": "user_1234567890"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Invoice not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/invoices/{id}/files": {
      "get": {
        "operationId": "getInvoicesByIdFiles",
        "tags": [
          "Invoices"
        ],
        "summary": "Get invoice files",
        "description": "Get XML and PDF files for an invoice.\n\n**gigstack Connect:** Access other teams' invoice files using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "SAT UUID (folio fiscal)",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          },
          {
            "name": "file_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pdf",
                "xml"
              ]
            },
            "description": "Type of file to retrieve. If not specified, returns both PDF and XML files"
          }
        ],
        "responses": {
          "200": {
            "description": "Files as base64 content, not URLs. Raw body (no `success`/`timestamp`). `file_type=pdf|xml` returns only that file.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "message"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "content": {
                            "type": "string",
                            "description": "Base64-encoded file content"
                          },
                          "filename": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "application/pdf",
                              "application/xml"
                            ]
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "content": "JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PC9UeXBlIC9DYXRhbG9nPj4K...",
                      "filename": "Yx7Kp2Lm9Qw4Rt6Bn1Vc.pdf",
                      "type": "application/pdf"
                    },
                    {
                      "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4K...",
                      "filename": "Yx7Kp2Lm9Qw4Rt6Bn1Vc.xml",
                      "type": "application/xml"
                    }
                  ],
                  "message": "Files retrieved successfully"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/{id}/send": {
      "post": {
        "operationId": "createInvoicesByIdSend",
        "tags": [
          "Invoices"
        ],
        "summary": "Resend invoice email",
        "description": "Resend an invoice email (PDF + XML attachments) to the client and/or additional recipients.\n\nThe client's email on the invoice is always included. Extra recipients can be added via the `emails` field.\n\n**gigstack Connect:** Send other teams' invoice emails using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Invoice UUID or gigstack invoice ID",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email"
                    },
                    "description": "Additional email recipients beyond the client email on the invoice",
                    "example": [
                      "accounting@example.com"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice email sent successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Invoice email sent successfully"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "recipients": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "uuid": {
                          "type": "string"
                        },
                        "attachments": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "message": "Invoice email sent successfully",
                  "data": {
                    "recipients": [
                      "contabilidad@ejemplo.com"
                    ],
                    "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                    "attachments": [
                      "Yx7Kp2Lm9Qw4Rt6Bn1Vc.pdf",
                      "Yx7Kp2Lm9Qw4Rt6Bn1Vc.xml"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request (cancelled invoice or no recipients)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Invoice not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}/support-documents": {
      "post": {
        "operationId": "createInvoicesByIdSupportDocuments",
        "tags": [
          "Invoices"
        ],
        "summary": "Upload support document",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nUpload a supporting document (contract, proof of delivery, etc.) for an invoice.\n\n**SAT 2026 Compliance:** The Mexican tax authority (SAT) can request supporting documentation\nto validate invoices. This endpoint helps maintain compliance.\n\n**gigstack Connect:** Upload documents for other teams' invoices using the `team` parameter.\n\n**Supported File Types:**\n- PDF files (.pdf)\n- Images (.png, .jpg, .jpeg, .webp)\n\n**File Size Limit:** 10MB\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "SAT UUID (folio fiscal)",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UploadSupportDocumentInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document uploaded. Standardized envelope (`timestamp` in epoch ms).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/SATDocument"
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "doc_1234567890",
                    "document_type": "contract",
                    "name": "Contrato de servicios 2026",
                    "description": null,
                    "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_1234567890%2Fdocuments%2Fcontrato-2026.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                    "file_name": "contrato-2026.pdf",
                    "file_size": 284913,
                    "mime_type": "application/pdf",
                    "compliance_status": "pending_review",
                    "created_at": 1767225600000,
                    "linked_entities": [
                      {
                        "entity_type": "invoice",
                        "entity_id": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                        "linked_at": 1767225600000
                      }
                    ]
                  },
                  "message": "Support document uploaded successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Invoice not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      },
      "get": {
        "operationId": "getInvoicesByIdSupportDocuments",
        "tags": [
          "Invoices"
        ],
        "summary": "List support documents",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nRetrieve all supporting documents attached to an invoice.\n\n**gigstack Connect:** View documents for other teams' invoices using the `team` parameter.\n\nDocuments are returned sorted by creation date (newest first).\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "SAT UUID (folio fiscal)",
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          }
        ],
        "responses": {
          "200": {
            "description": "Documents retrieved, newest first. Standardized envelope (`timestamp` in epoch ms).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SATDocument"
                      }
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "doc_1234567890",
                      "document_type": "contract",
                      "name": "Contrato de servicios 2026",
                      "description": null,
                      "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_1234567890%2Fdocuments%2Fcontrato-2026.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                      "file_name": "contrato-2026.pdf",
                      "file_size": 284913,
                      "mime_type": "application/pdf",
                      "compliance_status": "pending_review",
                      "created_at": 1767225600000,
                      "linked_entities": [
                        {
                          "entity_type": "invoice",
                          "entity_id": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                          "linked_at": 1767225600000
                        }
                      ]
                    }
                  ],
                  "message": "Support documents retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Invoice not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/invoices/{id}": {
      "get": {
        "tags": [
          "Invoices"
        ],
        "summary": "Get invoice",
        "operationId": "getInvoiceById",
        "description": "Retrieve any invoice by id, regardless of its CFDI type. The type-specific routes\n(`/invoices/income/{id}`, `/invoices/egress/{id}`, `/invoices/payment/{id}`) share this\nhandler but additionally assert the document's type and return `400` on a mismatch;\nthis route performs no type check.\n\n**gigstack Connect:** Access other teams' invoices using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "SAT UUID (folio fiscal).",
            "schema": {
              "type": "string"
            },
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          }
        ],
        "responses": {
          "200": {
            "description": "Invoice retrieved. **Raw legacy shape** — `{ \"message\": …, \"data\": … }`, with no\n`success` or `timestamp`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Invoice retrieved successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicIncomeInvoice"
                    }
                  }
                },
                "example": {
                  "message": "Invoice retrieved successfully",
                  "data": {
                    "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                    "idempotency_key": null,
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "created_at": 1767225600000,
                    "date": 1767225600000,
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "total": 1160,
                    "subtotal": 1000,
                    "discount": 0,
                    "taxes": 160,
                    "withholding_taxes": 0,
                    "series": "A",
                    "folio_number": 123,
                    "invoice_type": "I",
                    "use": "G03",
                    "payment_form": "03",
                    "payment_method": "PUE",
                    "livemode": true,
                    "owner": "user_1234567890",
                    "team": "team_1234567890",
                    "from": "api",
                    "status": "valid",
                    "payments": [
                      "payment_1234567890"
                    ],
                    "invoices": [],
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicios de consultoría profesional",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48"
                      }
                    ],
                    "metadata": {},
                    "emails": [
                      "contabilidad@ejemplo.com"
                    ],
                    "cancellation": null,
                    "stamp": {
                      "sello": "kQ3xZ9vR2mP7tL4wN8cB1yH6",
                      "stamp_at": 1767225600000
                    },
                    "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB&re=MEE200101ABC&rr=EKU9003173C9&tt=1160.00&fe=kQ3xZ9"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`{ \"message\": \"Missing id param\" }`, or on the type-specific routes `{ \"error\": \"Invoice type does not match\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized. Raw shape with only a `message` key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "`{ \"message\": \"Forbidden: invoices is not owned by the team\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`{ \"error\": \"Invoice data not found\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "`{ \"error\": \"Failed to get invoice due to unknown error. Please try again later.\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Invoices"
        ],
        "summary": "Cancel invoice",
        "operationId": "cancelInvoice",
        "description": "[Small working example](/recipes/cancellation)\n\n**Integration note:** This recipe covers Mexican CFDI cancellation. A provider acknowledgment does not prove final cancellation. Read the invoice and confirm its persisted status; public nested cancellation fields can be absent. Colombian annulment uses different semantics.\n\nCancel a specific invoice with SAT.\n\n**gigstack Connect:** Cancel other teams' invoices using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "SAT UUID (folio fiscal).",
            "schema": {
              "type": "string"
            },
            "example": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "motive"
                ],
                "properties": {
                  "motive": {
                    "type": "string",
                    "enum": [
                      "01",
                      "02",
                      "03",
                      "04"
                    ],
                    "example": "02",
                    "description": "SAT cancellation motive (`c_MotivoCancelacion`): `01` issued with errors, with a\nsubstitute CFDI (send `substitution_uuid`); `02` issued with errors, no substitute;\n`03` the operation did not take place; `04` nominative operation included in a global\ninvoice. The API only checks that the value is at most two characters; any other value\nis rejected by the SAT/PAC at cancellation time.\n"
                  },
                  "substitution_uuid": {
                    "type": "string",
                    "nullable": true,
                    "example": "12345678-1234-1234-1234-123456789012",
                    "description": "UUID of the substituting invoice (required for motive 01)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancellation accepted by the PAC. **Raw shape** — the PAC's cancellation\nresponse is spread at the top level alongside `cancellation_status`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "cancellation_status"
                  ],
                  "additionalProperties": true,
                  "properties": {
                    "cancellation_status": {
                      "type": "string",
                      "description": "Cancellation state reported by SAT.",
                      "example": "cancelled"
                    }
                  }
                },
                "example": {
                  "cancellation_status": "cancelled"
                }
              }
            }
          },
          "400": {
            "description": "Body validation failure — `{ \"message\": [ …validation errors… ] }` — or a generic\nCFDI/PAC cancellation error in the CFDI error shape (spread at the top level on\nthis operation, not nested under `message`).\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LegacyErrorResponse"
                    },
                    {
                      "$ref": "#/components/schemas/CfdiErrorResponse"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized. Raw shape with only a `message` key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "`{ \"message\": \"Livemode mismatch: API key and invoice must be in the same mode\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`{ \"message\": \"Invoice not found\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "412": {
            "description": "SAT not connected — the team has no valid CSD, or the certificate failed\nvalidation. Returned in the CFDI error shape with `retryable: false`.\nUpload a CSD via `POST /v2/teams/{id}/sat-connection` before retrying.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CfdiErrorResponse"
                },
                "example": {
                  "error": "El certificado de sello digital (CSD) no está configurado o no es válido.",
                  "code": "csd_validation_error",
                  "retryable": false
                }
              }
            }
          },
          "422": {
            "description": "The invoice was imported and stamped by an external PAC, so gigstack cannot\ncancel it. Cancel it through the original PAC provider instead.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                },
                "example": {
                  "message": "Imported invoices stamped by an external PAC cannot be canceled through gigstack. Please cancel through your original PAC provider."
                }
              }
            }
          },
          "500": {
            "description": "`{ \"error\": \"Internal server error\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "The PAC is unavailable. CFDI error shape with `retryable: true` — retry after a\nshort delay.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CfdiErrorResponse"
                },
                "example": {
                  "error": "El servicio de timbrado no está disponible en este momento. Vuelve a intentarlo en unos minutos.",
                  "code": "pac_unavailable",
                  "retryable": true
                }
              }
            }
          }
        }
      }
    },
    "/invoices/search": {
      "get": {
        "operationId": "getInvoicesSearch",
        "tags": [
          "Invoices"
        ],
        "summary": "Search invoices",
        "description": "Full-text search across invoices using Typesense. Provides fast, typo-tolerant search capabilities.\n\n**gigstack Connect:** Access other teams' invoices using the `team` parameter.\n\n**Search Capabilities:**\n- Search across client name, email, invoice UUID, description, and metadata\n- Typo-tolerant fuzzy matching\n- Paginated results\n\n**Requirements:**\n- Typesense must be configured for your team\n- The `q` (or `query`) parameter is required\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/SearchQueryParam"
          },
          {
            "$ref": "#/components/parameters/SearchQueryBackwardCompatParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/SearchPageParam"
          },
          {
            "$ref": "#/components/parameters/FieldsParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Invoices searched successfully",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SearchResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "message": "Invoices searched successfully",
                  "data": [
                    {
                      "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                      "idempotency_key": null,
                      "client": {
                        "id": "client_1234567890",
                        "name": "ESCUELA KEMPER URGATE",
                        "legal_name": "ESCUELA KEMPER URGATE",
                        "email": "contabilidad@ejemplo.com",
                        "bcc": [],
                        "phone": "+524421234567",
                        "tax_id": "EKU9003173C9",
                        "tax_system": "601",
                        "use": "G03",
                        "address": {
                          "street": "Av. Constituyentes",
                          "exterior": "1000",
                          "neighborhood": "Centro",
                          "city": "Querétaro",
                          "state": "QRO",
                          "zip": "76000",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "efos": {
                          "is_valid": true
                        },
                        "metadata": {},
                        "livemode": true,
                        "from": "api",
                        "owner": "user_1234567890",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      },
                      "created_at": 1767225600000,
                      "date": 1767225600000,
                      "currency": "MXN",
                      "exchange_rate": 1,
                      "total": 1160,
                      "subtotal": 1000,
                      "discount": 0,
                      "taxes": 160,
                      "withholding_taxes": 0,
                      "series": "A",
                      "folio_number": 123,
                      "invoice_type": "I",
                      "use": "G03",
                      "payment_form": "03",
                      "payment_method": "PUE",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "from": "api",
                      "status": "valid",
                      "payments": [
                        "payment_1234567890"
                      ],
                      "invoices": [],
                      "items": [
                        {
                          "id": "service_1234567890",
                          "description": "Servicios de consultoría profesional",
                          "quantity": 1,
                          "unit_price": 1000,
                          "product_key": "80141503",
                          "unit_key": "E48"
                        }
                      ],
                      "metadata": {},
                      "emails": [
                        "contabilidad@ejemplo.com"
                      ],
                      "cancellation": null,
                      "stamp": {
                        "sello": "kQ3xZ9vR2mP7tL4wN8cB1yH6",
                        "stamp_at": 1767225600000
                      },
                      "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB&re=MEE200101ABC&rr=EKU9003173C9&tt=1160.00&fe=kQ3xZ9"
                    }
                  ],
                  "found": 1,
                  "page": 1,
                  "per_page": 10,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "missing_query": {
                    "summary": "Missing query parameter",
                    "value": {
                      "error": {
                        "code": "missing_query",
                        "message": "Query parameter is required"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "missing_typesense_key": {
                    "summary": "Typesense not configured",
                    "value": {
                      "error": {
                        "code": "missing_typesense_key",
                        "message": "Typesense API key not configured for this team"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/draft": {
      "get": {
        "operationId": "getInvoicesDraft",
        "tags": [
          "Invoices",
          "Draft Invoices (Pre-Facturas)"
        ],
        "summary": "List draft invoices",
        "description": "Retrieve a paginated list of draft invoices (pre-facturas).\n\nDrafts are incomplete invoices that have not been stamped yet. Use them to prepare invoices incrementally before finalizing.\n\n**gigstack Connect:** Access other teams' drafts using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "name": "invoice_type",
            "in": "query",
            "description": "Filter by invoice type (I = Income, E = Egress)",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "I",
                "E"
              ]
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "description": "Filter by client ID",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Drafts retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                },
                "example": {
                  "success": true,
                  "message": "Drafts retrieved successfully",
                  "data": [
                    {
                      "id": "Wm4R8tY2uI6oP0aS3dF7",
                      "draft": true,
                      "invoice_type": "I",
                      "client": {
                        "id": "client_1234567890",
                        "name": "ESCUELA KEMPER URGATE",
                        "legal_name": "ESCUELA KEMPER URGATE",
                        "email": "contabilidad@ejemplo.com",
                        "bcc": [],
                        "phone": "+524421234567",
                        "tax_id": "EKU9003173C9",
                        "tax_system": "601",
                        "use": "G03",
                        "address": {
                          "street": "Av. Constituyentes",
                          "exterior": "1000",
                          "neighborhood": "Centro",
                          "city": "Querétaro",
                          "state": "QRO",
                          "zip": "76000",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "efos": {
                          "is_valid": true
                        },
                        "metadata": {},
                        "livemode": true,
                        "from": "api",
                        "owner": "user_1234567890",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      },
                      "created_at": 1767225600000,
                      "updated_at": 1767225600000,
                      "currency": "MXN",
                      "exchange_rate": 1,
                      "total": 5800,
                      "subtotal": 5000,
                      "discount": 0,
                      "series": "A",
                      "folio_number": null,
                      "use": "G03",
                      "payment_form": "03",
                      "payment_method": "PUE",
                      "date": null,
                      "livemode": true,
                      "owner": "user_1234567890",
                      "from": "api",
                      "status": "draft",
                      "items": [
                        {
                          "quantity": 1,
                          "description": "Servicio de consultoría",
                          "product_key": "80141503",
                          "unit_key": "ACT",
                          "unit_name": "Actividad",
                          "unit_price": 5000,
                          "taxes": [
                            {
                              "type": "IVA",
                              "rate": 0.16,
                              "factor": "Tasa",
                              "withholding": false,
                              "inclusive": false
                            }
                          ]
                        }
                      ],
                      "metadata": {
                        "project_id": "PROJ-2024-001"
                      },
                      "automation_type": "none",
                      "emails": [],
                      "related_documents": [],
                      "complements": []
                    }
                  ],
                  "next": null,
                  "has_more": false,
                  "total_results": 1,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          }
        }
      },
      "post": {
        "operationId": "createInvoicesDraft",
        "tags": [
          "Invoices",
          "Draft Invoices (Pre-Facturas)"
        ],
        "summary": "Create draft invoice (pre-factura)",
        "description": "[Small working example](/recipes/invoice)\n\n**Integration note:** Save data.id as the draft ID and inspect data.livemode before testing fiscal operations. Draft creation does not stamp a CFDI. Read [shared fields](/concepts/shared-fields) and the [Mexico](/countries/mexico) or [Colombia](/countries/colombia) guide for country-specific meaning. The linked fiscal recipes and staging issuance results use a Mexican issuer.\n\nCreate a new draft invoice (pre-factura) that can be edited and stamped later.\n\nOnly the `invoice_type` field is required. All other fields are optional, allowing you to build the invoice incrementally:\n\n1. **Create** a draft with minimal data (`invoice_type`)\n2. **Update** the draft as data becomes available (client, items, payment details)\n3. **Preview** the draft to generate a PDF with \"Sin Validez Fiscal\" watermark\n4. **Stamp** the draft when ready to finalize it into a valid CFDI\n\n**gigstack Connect:** Create drafts for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DraftInvoiceInput"
              },
              "example": {
                "invoice_type": "I",
                "currency": "MXN",
                "use": "G03",
                "payment_form": "03",
                "payment_method": "PUE",
                "client": {
                  "id": "client_1234567890"
                },
                "items": [
                  {
                    "quantity": 1,
                    "description": "Servicio de consultoría",
                    "product_key": "80141503",
                    "unit_key": "ACT",
                    "unit_name": "Actividad",
                    "unit_price": 5000,
                    "taxes": [
                      {
                        "type": "IVA",
                        "rate": 0.16,
                        "factor": "Tasa",
                        "withholding": false,
                        "inclusive": false
                      }
                    ]
                  }
                ],
                "metadata": {
                  "project_id": "PROJ-2024-001"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Draft created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Draft created"
                    },
                    "data": {
                      "$ref": "#/components/schemas/DraftInvoiceOutput"
                    }
                  }
                },
                "example": {
                  "message": "Draft created",
                  "data": {
                    "id": "Wm4R8tY2uI6oP0aS3dF7",
                    "draft": true,
                    "invoice_type": "I",
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "created_at": 1767225600000,
                    "updated_at": 1767225600000,
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "total": 5800,
                    "subtotal": 5000,
                    "discount": 0,
                    "series": "A",
                    "folio_number": null,
                    "use": "G03",
                    "payment_form": "03",
                    "payment_method": "PUE",
                    "date": null,
                    "livemode": true,
                    "owner": "user_1234567890",
                    "from": "api",
                    "status": "draft",
                    "items": [
                      {
                        "quantity": 1,
                        "description": "Servicio de consultoría",
                        "product_key": "80141503",
                        "unit_key": "ACT",
                        "unit_name": "Actividad",
                        "unit_price": 5000,
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false,
                            "inclusive": false
                          }
                        ]
                      }
                    ],
                    "metadata": {
                      "project_id": "PROJ-2024-001"
                    },
                    "automation_type": "none",
                    "emails": [],
                    "related_documents": [],
                    "complements": []
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          }
        }
      }
    },
    "/invoices/draft/{id}": {
      "get": {
        "operationId": "getInvoicesDraftById",
        "tags": [
          "Invoices",
          "Draft Invoices (Pre-Facturas)"
        ],
        "summary": "Get draft invoice",
        "description": "Retrieve a specific draft invoice by ID. Includes the preview PDF (base64) if one has been generated.\n\n**gigstack Connect:** Access other teams' drafts using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Draft invoice ID",
            "example": "inv-draft_9f2c1a7b4e6d8035c1af92be"
          }
        ],
        "responses": {
          "200": {
            "description": "Draft retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Draft retrieved successfully"
                    },
                    "data": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/DraftInvoiceOutput"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "preview_pdf": {
                              "type": "string",
                              "description": "Base64-encoded preview PDF (if previously generated)"
                            }
                          }
                        }
                      ]
                    }
                  }
                },
                "example": {
                  "message": "Draft retrieved successfully",
                  "data": {
                    "id": "Wm4R8tY2uI6oP0aS3dF7",
                    "draft": true,
                    "invoice_type": "I",
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "created_at": 1767225600000,
                    "updated_at": 1767225600000,
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "total": 5800,
                    "subtotal": 5000,
                    "discount": 0,
                    "series": "A",
                    "folio_number": null,
                    "use": "G03",
                    "payment_form": "03",
                    "payment_method": "PUE",
                    "date": null,
                    "livemode": true,
                    "owner": "user_1234567890",
                    "from": "api",
                    "status": "draft",
                    "items": [
                      {
                        "quantity": 1,
                        "description": "Servicio de consultoría",
                        "product_key": "80141503",
                        "unit_key": "ACT",
                        "unit_name": "Actividad",
                        "unit_price": 5000,
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false,
                            "inclusive": false
                          }
                        ]
                      }
                    ],
                    "metadata": {
                      "project_id": "PROJ-2024-001"
                    },
                    "automation_type": "none",
                    "emails": [],
                    "related_documents": [],
                    "complements": []
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Draft not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateInvoicesDraftById",
        "tags": [
          "Invoices",
          "Draft Invoices (Pre-Facturas)"
        ],
        "summary": "Update draft invoice",
        "description": "[Small working example](/recipes/invoice)\n\nUpdate a saved invoice draft. Send the complete intended body, including items. In the staging verification on 2026-10-08, a notes-only update cleared items; several omitted fields also receive defaults. Read the draft back and compare it before stamping. Do not assume partial PATCH semantics.\n\nUse the team parameter only with the documented gigstack Connect permissions.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Draft invoice ID",
            "example": "inv-draft_9f2c1a7b4e6d8035c1af92be"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DraftInvoiceUpdateInput"
              },
              "example": {
                "client": {
                  "id": "client_updated_id"
                },
                "items": [
                  {
                    "quantity": 2,
                    "description": "Updated service",
                    "unit_price": 3000,
                    "product_key": "80141503",
                    "unit_key": "ACT",
                    "unit_name": "Actividad",
                    "taxes": [
                      {
                        "type": "IVA",
                        "rate": 0.16,
                        "factor": "Tasa",
                        "withholding": false,
                        "inclusive": false
                      }
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Draft updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Draft updated"
                    },
                    "data": {
                      "$ref": "#/components/schemas/DraftInvoiceOutput"
                    }
                  }
                },
                "example": {
                  "message": "Draft updated",
                  "data": {
                    "id": "Wm4R8tY2uI6oP0aS3dF7",
                    "draft": true,
                    "invoice_type": "I",
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "created_at": 1767225600000,
                    "updated_at": 1767225660000,
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "total": 5800,
                    "subtotal": 5000,
                    "discount": 0,
                    "series": "A",
                    "folio_number": null,
                    "use": "G03",
                    "payment_form": "03",
                    "payment_method": "PUE",
                    "date": null,
                    "livemode": true,
                    "owner": "user_1234567890",
                    "from": "api",
                    "status": "draft",
                    "items": [
                      {
                        "quantity": 1,
                        "description": "Servicio de consultoría",
                        "product_key": "80141503",
                        "unit_key": "ACT",
                        "unit_name": "Actividad",
                        "unit_price": 5000,
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false,
                            "inclusive": false
                          }
                        ]
                      }
                    ],
                    "metadata": {
                      "project_id": "PROJ-2024-001"
                    },
                    "automation_type": "none",
                    "emails": [],
                    "related_documents": [],
                    "complements": []
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error or document is not a draft",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Draft not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteInvoicesDraftById",
        "tags": [
          "Invoices",
          "Draft Invoices (Pre-Facturas)"
        ],
        "summary": "Delete draft invoice",
        "description": "Permanently delete a draft invoice. This also removes any generated preview files.\n\n**Note:** Only drafts can be deleted. For stamped invoices, use the cancel endpoint instead.\n\n**gigstack Connect:** Delete other teams' drafts using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Draft invoice ID",
            "example": "inv-draft_9f2c1a7b4e6d8035c1af92be"
          }
        ],
        "responses": {
          "200": {
            "description": "Draft deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Draft deleted"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "message": "Draft deleted",
                  "data": {
                    "id": "Wm4R8tY2uI6oP0aS3dF7"
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Draft not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/draft/{id}/stamp": {
      "post": {
        "operationId": "createInvoicesDraftByIdStamp",
        "tags": [
          "Invoices",
          "Draft Invoices (Pre-Facturas)"
        ],
        "summary": "Stamp draft invoice (finalize)",
        "description": "[Small working example](/recipes/invoice)\n\n**Integration note:** Verified staging result: HTTP 200, data.uuid, data.status valid, and no data.id. Retrieve the issued invoice using the returned UUID, not the former draft ID. The stored draft determines livemode; a test key does not convert an existing live draft into a test draft. Read [shared fields](/concepts/shared-fields) and the [Mexico](/countries/mexico) or [Colombia](/countries/colombia) guide for country-specific meaning. The linked fiscal recipes and staging issuance results use a Mexican issuer.\n\nStamp (finalize) a draft invoice into a valid CFDI with SAT.\n\nThe draft **must** have all required fields before stamping:\n- `client` — a valid client with fiscal data\n- `items` — at least one item\n- `use` — CFDI use code (e.g., `G03` gastos en general, `S01` sin efectos fiscales)\n- `payment_form` — payment form code (e.g., 03, 99)\n- `payment_method` — PUE or PPD\n- `currency` — currency code (e.g., MXN, USD)\n\nAfter stamping:\n- The draft document is deleted\n- A new stamped invoice document is created with a UUID from SAT\n- The response follows the same format as `POST /invoices/income`\n\n**gigstack Connect:** Stamp other teams' drafts using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Draft invoice ID",
            "example": "inv-draft_9f2c1a7b4e6d8035c1af92be"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "return_files": {
                    "type": "boolean",
                    "description": "Include base64 XML and PDF in response",
                    "example": true
                  },
                  "send_email": {
                    "type": "boolean",
                    "description": "Whether to send the document via email to the client. Defaults to true.",
                    "example": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice created from draft",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Invoice created from draft"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicIncomeInvoice"
                    }
                  }
                },
                "example": {
                  "message": "Invoice created from draft",
                  "data": {
                    "uuid": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                    "idempotency_key": null,
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "created_at": 1767225600000,
                    "date": 1767225600000,
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "total": 1160,
                    "subtotal": 1000,
                    "discount": 0,
                    "taxes": 160,
                    "withholding_taxes": 0,
                    "series": "A",
                    "folio_number": 123,
                    "invoice_type": "I",
                    "use": "G03",
                    "payment_form": "03",
                    "payment_method": "PUE",
                    "livemode": true,
                    "owner": "user_1234567890",
                    "team": "team_1234567890",
                    "from": "api",
                    "status": "valid",
                    "payments": [
                      "payment_1234567890"
                    ],
                    "invoices": [],
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicios de consultoría profesional",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48"
                      }
                    ],
                    "metadata": {},
                    "emails": [
                      "contabilidad@ejemplo.com"
                    ],
                    "cancellation": null,
                    "stamp": {
                      "sello": "kQ3xZ9vR2mP7tL4wN8cB1yH6",
                      "stamp_at": 1767225600000
                    },
                    "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB&re=MEE200101ABC&rr=EKU9003173C9&tt=1160.00&fe=kQ3xZ9"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Draft is incomplete, not a draft, or the stamp failed. All bodies are **raw**\n(`{ \"message\": … }`), never the standardized envelope. Messages emitted:\n`Missing draft id`, `Billing account not found`,\n`Document is not a draft — it may have already been stamped`,\n`Draft is incomplete — a client and at least one item are required to stamp`,\n`Draft is missing CFDI use (use)`, `Draft is missing payment form (payment_form)`,\n`Draft is missing payment method (payment_method)`, `Draft is missing currency`,\n`Invalid currency`, `Exchange rate not found`. A generic CFDI/PAC stamping\nfailure is nested under `message` in the CFDI error shape.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LegacyErrorResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "message": {
                          "$ref": "#/components/schemas/CfdiErrorResponse"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "missing_client": {
                    "summary": "Missing client",
                    "value": {
                      "message": "Draft is incomplete — a client and at least one item are required to stamp"
                    }
                  },
                  "missing_use": {
                    "summary": "Missing CFDI use",
                    "value": {
                      "message": "Draft is missing CFDI use (use)"
                    }
                  },
                  "not_a_draft": {
                    "summary": "Already stamped",
                    "value": {
                      "message": "Document is not a draft — it may have already been stamped"
                    }
                  },
                  "pac_error": {
                    "summary": "Generic PAC stamping failure",
                    "value": {
                      "message": {
                        "error": "Error al timbrar la factura: CFDI40147 - El campo UsoCFDI no es válido",
                        "code": "stamping_error",
                        "providerMessage": "CFDI40147 - El campo UsoCFDI no es válido",
                        "retryable": false
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`{ \"message\": \"Unauthorized\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "`{ \"message\": \"Forbidden: draft is not owned by the team\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`{ \"message\": \"Draft not found\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "412": {
            "description": "**SAT not connected** — no valid CSD for the team. CFDI error shape nested under\n`message`, `retryable: false`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "$ref": "#/components/schemas/CfdiErrorResponse"
                    }
                  }
                },
                "example": {
                  "message": {
                    "error": "El certificado de sello digital (CSD) no está configurado o no es válido.",
                    "code": "csd_validation_error",
                    "retryable": false
                  }
                }
              }
            }
          },
          "429": {
            "description": "**Team credit limit reached.** Checked before stamping — the draft is left intact\nand no credit is consumed.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditLimitResponse"
                },
                "example": {
                  "message": "Team credit limit reached",
                  "error": "Credit limit of 100 documents reached for this billing period",
                  "credit_limit": 100,
                  "used_credits": 100
                }
              }
            }
          },
          "500": {
            "description": "`{ \"message\": \"Failed to save stamped invoice\", \"error\": { \"code\": \"invoice_save_error\" } }`\nor `{ \"message\": \"An error occurred while stamping draft\", \"error\": { \"code\": …, \"message\": … } }`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "**PAC unavailable.** CFDI error shape nested under `message` with\n`retryable: true`. The draft is untouched — retry after a short delay.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "$ref": "#/components/schemas/CfdiErrorResponse"
                    }
                  }
                },
                "example": {
                  "message": {
                    "error": "El servicio de timbrado no está disponible en este momento. Vuelve a intentarlo en unos minutos.",
                    "code": "pac_unavailable",
                    "retryable": true
                  }
                }
              }
            }
          }
        }
      }
    },
    "/invoices/draft/{id}/preview": {
      "post": {
        "operationId": "createInvoicesDraftByIdPreview",
        "tags": [
          "Invoices",
          "Draft Invoices (Pre-Facturas)"
        ],
        "summary": "Generate draft preview PDF (pre-factura)",
        "description": "Generate a preview PDF for a draft invoice with a **\"Sin Validez Fiscal\"** watermark.\n\nThis is the **pre-factura** feature: it runs the full CFDI pipeline (normalization, XML mapping, PDF generation) without actually stamping with SAT. The generated PDF is saved and can be retrieved later via `GET /invoices/draft/{id}`.\n\n**Requirements:**\n- Draft must have at least a `client` and one `item`\n\n**What you get:**\n- A PDF that looks like a real CFDI invoice\n- UUID shows `PREFACTURA-0000-0000-0000-SINVALIDEZ`\n- \"Sin Validez Fiscal\" watermark overlay\n- Useful for client approval before stamping\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Draft invoice ID",
            "example": "inv-draft_9f2c1a7b4e6d8035c1af92be"
          }
        ],
        "responses": {
          "200": {
            "description": "Preview PDF generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Preview PDF generated"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "pdf": {
                          "type": "string",
                          "description": "Base64-encoded PDF with \"Sin Validez Fiscal\" watermark"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "message": "Preview PDF generated",
                  "data": {
                    "pdf": "JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PC9UeXBlIC9DYXRhbG9nPj4K..."
                  }
                }
              }
            }
          },
          "400": {
            "description": "Draft is incomplete. **Raw shape** — `{ \"message\": … }`, not the standardized envelope.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                },
                "examples": {
                  "incomplete": {
                    "summary": "Missing client or items",
                    "value": {
                      "message": "Draft needs at least a client and one item to generate preview"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Draft not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/payments": {
      "get": {
        "operationId": "listPayments",
        "tags": [
          "Payments"
        ],
        "summary": "List payments",
        "description": "Retrieve a paginated list of payments with powerful filtering capabilities.\n\n**gigstack Connect:** Access other teams' payments using the `team` parameter.\n\n**Filtering Options:**\n- Filter by payment status, currency, amount\n- Filter by client ID, email, tax ID (RFC), or name\n- Filter by metadata fields using dot or underscore notation (e.g., `metadata.order_id` or `metadata_order_id`)\n- Filter by creation date using comparison operators\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGtParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLtParam"
          },
          {
            "$ref": "#/components/parameters/PaymentStatusParam"
          },
          {
            "$ref": "#/components/parameters/PaymentCurrencyParam"
          },
          {
            "$ref": "#/components/parameters/PaymentAmountParam"
          },
          {
            "$ref": "#/components/parameters/PaymentClientIdParam"
          },
          {
            "$ref": "#/components/parameters/PaymentEmailParam"
          },
          {
            "$ref": "#/components/parameters/PaymentTaxIdParam"
          },
          {
            "$ref": "#/components/parameters/PaymentClientNameParam"
          },
          {
            "name": "metadata.{key}",
            "in": "query",
            "description": "Filter by any metadata field using dot notation (e.g., `metadata.order_id=ORD-123`)\nor underscore notation (e.g., `metadata_order_id=ORD-123`).\nBoth formats are supported and equivalent.\n",
            "required": false,
            "schema": {
              "type": "string"
            },
            "style": "form"
          }
        ],
        "responses": {
          "200": {
            "description": "Payments retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                },
                "example": {
                  "success": true,
                  "message": "Payments retrieved successfully",
                  "data": [
                    {
                      "id": "payment_1234567890",
                      "client": {
                        "id": "client_1234567890",
                        "name": "ESCUELA KEMPER URGATE",
                        "legal_name": "ESCUELA KEMPER URGATE",
                        "email": "contabilidad@ejemplo.com",
                        "bcc": [],
                        "phone": "+524421234567",
                        "tax_id": "EKU9003173C9",
                        "tax_system": "601",
                        "use": "G03",
                        "address": {
                          "street": "Av. Constituyentes",
                          "exterior": "1000",
                          "neighborhood": "Centro",
                          "city": "Querétaro",
                          "state": "QRO",
                          "zip": "76000",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "efos": {
                          "is_valid": true
                        },
                        "metadata": {},
                        "livemode": true,
                        "from": "api",
                        "owner": "user_1234567890",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      },
                      "emails": [
                        "contabilidad@ejemplo.com"
                      ],
                      "currency": "MXN",
                      "allowed_payment_methods": [
                        "card",
                        "bank"
                      ],
                      "exchange_rate": 1,
                      "items": [
                        {
                          "id": "service_1234567890",
                          "description": "Servicios de consultoría profesional",
                          "quantity": 1,
                          "unit_price": 1000,
                          "product_key": "80141503",
                          "unit_key": "E48",
                          "unit_name": "Unidad de servicio",
                          "taxes": [
                            {
                              "type": "IVA",
                              "rate": 0.16,
                              "factor": "Tasa",
                              "withholding": false
                            }
                          ],
                          "team": "team_1234567890",
                          "created_at": 1767225600000,
                          "from": "api"
                        }
                      ],
                      "metadata": {},
                      "team": "team_1234567890",
                      "idempotency_key": "payment-2026-0001",
                      "from": "api",
                      "invoices": [
                        "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
                      ],
                      "livemode": true,
                      "owner": "user_1234567890",
                      "payment_form": "03",
                      "payments": [],
                      "receipts": [],
                      "refunds": [],
                      "short_url": "https://gigstack.xyz/Xk3mP9",
                      "success_url": null,
                      "status": "succeeded",
                      "total": 1160,
                      "total_refunded": 0,
                      "subtotal": 1000,
                      "taxes": 160,
                      "discount": 0,
                      "withholding_taxes": 0,
                      "created_at": 1767225600000,
                      "succeeded_at": 1767225900000,
                      "payment_processor": "api"
                    }
                  ],
                  "next": null,
                  "has_more": false,
                  "total_results": 1,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/payments/search": {
      "get": {
        "operationId": "getPaymentsSearch",
        "tags": [
          "Payments"
        ],
        "summary": "Search payments",
        "description": "Full-text search across payments using Typesense. Provides fast, typo-tolerant search capabilities.\n\n**gigstack Connect:** Access other teams' payments using the `team` parameter.\n\n**Search Capabilities:**\n- Search across client name, email, payment ID, description, and metadata\n- Typo-tolerant fuzzy matching\n- Filter search results by status, currency, or client ID\n- Paginated results\n\n**Requirements:**\n- Typesense must be configured for your team\n- The `q` (or `query`) parameter is required\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/SearchQueryParam"
          },
          {
            "$ref": "#/components/parameters/SearchQueryBackwardCompatParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/SearchPageParam"
          },
          {
            "$ref": "#/components/parameters/FieldsParam"
          },
          {
            "$ref": "#/components/parameters/PaymentStatusParam"
          },
          {
            "$ref": "#/components/parameters/PaymentCurrencyParam"
          },
          {
            "$ref": "#/components/parameters/PaymentClientIdParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Payments searched successfully",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SearchResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "message": "Payments searched successfully",
                  "data": [
                    {
                      "id": "payment_1234567890",
                      "client": {
                        "id": "client_1234567890",
                        "name": "ESCUELA KEMPER URGATE",
                        "legal_name": "ESCUELA KEMPER URGATE",
                        "email": "contabilidad@ejemplo.com",
                        "bcc": [],
                        "phone": "+524421234567",
                        "tax_id": "EKU9003173C9",
                        "tax_system": "601",
                        "use": "G03",
                        "address": {
                          "street": "Av. Constituyentes",
                          "exterior": "1000",
                          "neighborhood": "Centro",
                          "city": "Querétaro",
                          "state": "QRO",
                          "zip": "76000",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "efos": {
                          "is_valid": true
                        },
                        "metadata": {},
                        "livemode": true,
                        "from": "api",
                        "owner": "user_1234567890",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      },
                      "emails": [
                        "contabilidad@ejemplo.com"
                      ],
                      "currency": "MXN",
                      "allowed_payment_methods": [
                        "card",
                        "bank"
                      ],
                      "exchange_rate": 1,
                      "items": [
                        {
                          "id": "service_1234567890",
                          "description": "Servicios de consultoría profesional",
                          "quantity": 1,
                          "unit_price": 1000,
                          "product_key": "80141503",
                          "unit_key": "E48",
                          "unit_name": "Unidad de servicio",
                          "taxes": [
                            {
                              "type": "IVA",
                              "rate": 0.16,
                              "factor": "Tasa",
                              "withholding": false
                            }
                          ],
                          "team": "team_1234567890",
                          "created_at": 1767225600000,
                          "from": "api"
                        }
                      ],
                      "metadata": {},
                      "team": "team_1234567890",
                      "idempotency_key": "payment-2026-0001",
                      "from": "api",
                      "invoices": [
                        "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
                      ],
                      "livemode": true,
                      "owner": "user_1234567890",
                      "payment_form": "03",
                      "payments": [],
                      "receipts": [],
                      "refunds": [],
                      "short_url": "https://gigstack.xyz/Xk3mP9",
                      "success_url": null,
                      "status": "succeeded",
                      "total": 1160,
                      "total_refunded": 0,
                      "subtotal": 1000,
                      "taxes": 160,
                      "discount": 0,
                      "withholding_taxes": 0,
                      "created_at": 1767225600000,
                      "succeeded_at": 1767225900000,
                      "payment_processor": "api"
                    }
                  ],
                  "found": 1,
                  "page": 1,
                  "per_page": 10,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "missing_query": {
                    "summary": "Missing query parameter",
                    "value": {
                      "error": {
                        "code": "missing_query",
                        "message": "Query parameter is required"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "missing_typesense_key": {
                    "summary": "Typesense not configured",
                    "value": {
                      "error": {
                        "code": "missing_typesense_key",
                        "message": "Typesense API key not configured for this team"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/activate/status": {
      "get": {
        "operationId": "getInvoicesDownloadActivateStatus",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Check activation status",
        "description": "Check whether Descarga Masiva SAT is activated for your team and what action (if any) is required.\n\n**Possible statuses:**\n- `active` — Already activated, FIEL setup and scheduling are available\n- `needs_activation` — Your plan includes the feature; call `POST /invoices/download/activate` to turn it on (no extra charge)\n- `needs_addon` — Your plan doesn't include the feature; activating adds the $0.20 MXN/XML download meter to your subscription (no monthly fee)\n- `needs_upgrade` — Free plan; upgrade first at `/memberships`\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Activation status retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "active",
                            "needs_activation",
                            "needs_addon",
                            "needs_upgrade"
                          ],
                          "example": "needs_activation"
                        },
                        "planIncludesFeature": {
                          "type": "boolean",
                          "example": true
                        },
                        "isActivated": {
                          "type": "boolean",
                          "example": false
                        },
                        "pricing": {
                          "type": "object",
                          "properties": {
                            "perDownload": {
                              "type": "string",
                              "example": "$0.20 MXN"
                            },
                            "addonMonthly": {
                              "type": "string",
                              "nullable": true,
                              "example": null
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "status": "active",
                    "planIncludesFeature": false,
                    "isActivated": true,
                    "pricing": {
                      "perDownload": "$0.20 MXN",
                      "addonMonthly": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/activate": {
      "post": {
        "operationId": "createInvoicesDownloadActivate",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Activate Descarga Masiva SAT",
        "description": "Activate Descarga Masiva SAT for your team. Billing is adjusted automatically based on your plan:\n\n- **Plan includes feature** (`needs_activation` status): Activation is free — you only pay $0.20 MXN per XML downloaded.\n- **Plan without feature** (`needs_addon` status): Activation adds only the $0.20 MXN per XML download meter to your subscription. There is no monthly base fee.\n\nOnce activated, upload your FIEL via `POST /invoices/download/fiel` to complete setup.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Activated successfully (or already active)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Descarga Masiva activada. Cada descarga de XML consumirá créditos SAT."
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": [
                            "included",
                            "addon"
                          ],
                          "example": "included"
                        },
                        "activated": {
                          "type": "boolean",
                          "example": true
                        },
                        "alreadyActive": {
                          "type": "boolean",
                          "description": "Present and true when the feature was already active"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Descarga Masiva activada. Cada descarga de XML tiene un costo de $0.20 MXN.",
                  "data": {
                    "type": "addon",
                    "activated": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request — no active subscription or free plan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — free plan cannot purchase add-on",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/deactivate": {
      "post": {
        "operationId": "createInvoicesDownloadDeactivate",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Deactivate Descarga Masiva SAT",
        "description": "Deactivate Descarga Masiva SAT for your team. Scheduled downloads stop immediately. If the feature was billed as an add-on, the charge is removed from your subscription (prorated). Any remaining XML downloads in the current period are still billed at period end.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Deactivated successfully (or already inactive)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Descarga Masiva desactivada."
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Descarga Masiva desactivada."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/fiel": {
      "post": {
        "operationId": "createInvoicesDownloadFiel",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Upload FIEL credentials",
        "description": "Upload your FIEL (Firma Electrónica Avanzada) credentials to enable SAT bulk downloads.\n\n**This is the main setup endpoint.** It accepts your `.cer` and `.key` files, validates them, and — if `sync_start_date` and `phone` are provided — automatically registers your business with the SAT in the same request. No separate `/register` call needed.\n\n**What it does:**\n1. Validates the certificate format, extracts your RFC, and checks it matches your gigstack team RFC\n2. Verifies the certificate is not expired\n3. Securely encrypts and stores your credentials\n4. If `sync_start_date` + `phone` are provided → registers your business with the SAT immediately and enables sync (`registered: true` in the response)\n\n**Request format:** `multipart/form-data`\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `cert` | file | Yes | `.cer` file (DER-encoded certificate from SAT) |\n| `key` | file | Yes | `.key` file (DER-encoded encrypted private key from SAT) |\n| `password` | string | Yes | Password for the `.key` file |\n| `sync_start_date` | string | Recommended | Start date for SAT sync (`YYYY-MM-DD`, up to 71 months back) |\n| `phone` | string | Recommended | Contact phone in international format (e.g. `+5215512345678`) |\n\n> **Note:** The FIEL is different from the CSD (Certificado de Sello Digital). The CSD is used to stamp CFDI invoices. The FIEL is used to authenticate with the SAT for bulk downloads.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "cert",
                  "key",
                  "password"
                ],
                "properties": {
                  "cert": {
                    "type": "string",
                    "format": "binary",
                    "description": ".cer file — DER-encoded certificate from SAT"
                  },
                  "key": {
                    "type": "string",
                    "format": "binary",
                    "description": ".key file — DER-encoded encrypted private key from SAT"
                  },
                  "password": {
                    "type": "string",
                    "description": "Password for the .key file"
                  },
                  "sync_start_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Start date for historical SAT sync (YYYY-MM-DD, up to 71 months back)",
                    "example": "2023-01-01"
                  },
                  "phone": {
                    "type": "string",
                    "description": "Contact phone in international format",
                    "example": "+5215512345678"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "FIEL uploaded (and optionally registered) successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "FIEL credentials stored successfully. Business registered with SAT sync enabled."
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rfc": {
                          "type": "string",
                          "example": "XAXX010101000"
                        },
                        "expires_at": {
                          "type": "integer",
                          "description": "Certificate expiry timestamp (ms)",
                          "example": 1893456000000
                        },
                        "expires_at_readable": {
                          "type": "string",
                          "example": "2029-12-31T00:00:00.000Z"
                        },
                        "serial_number": {
                          "type": "string",
                          "example": "00001000000504465028"
                        },
                        "sync_start_date": {
                          "type": "string",
                          "nullable": true,
                          "example": "2023-01-01"
                        },
                        "phone": {
                          "type": "string",
                          "nullable": true,
                          "example": "+5215512345678"
                        },
                        "registered": {
                          "type": "boolean",
                          "description": "true if auto-registration with SAT succeeded",
                          "example": true
                        },
                        "registered_at": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Registration timestamp (ms), null if not yet registered"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "FIEL credentials stored successfully",
                  "data": {
                    "rfc": "MEE200101ABC",
                    "expires_at": 1893456000000,
                    "expires_at_readable": "2030-01-01T06:00:00.000Z",
                    "serial_number": "00001000000712345678",
                    "sync_start_date": null,
                    "phone": "+525512345678",
                    "registered": true,
                    "registered_at": 1767225600000
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request — missing files, RFC mismatch, expired certificate, invalid format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/register": {
      "post": {
        "operationId": "createInvoicesDownloadRegister",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Register business with SAT (manual)",
        "description": "Manually register your business with the SAT. Only needed if the automatic registration during `POST /invoices/download/fiel` failed.\n\n**In most cases you don't need to call this directly** — `POST /invoices/download/fiel` handles registration automatically when `sync_start_date` and `phone` are provided.\n\nRequires that FIEL credentials were already uploaded via `POST /invoices/download/fiel`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "sync_start_date",
                  "phone"
                ],
                "properties": {
                  "sync_start_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Start date for SAT sync (YYYY-MM-DD, max 71 months back)",
                    "example": "2023-01-01"
                  },
                  "phone": {
                    "type": "string",
                    "description": "Contact phone in international format (+52...)",
                    "example": "+5215512345678"
                  },
                  "legal_name": {
                    "type": "string",
                    "description": "Business legal name (defaults to team legal name)"
                  },
                  "max_monthly_invoices": {
                    "type": "integer",
                    "description": "Maximum monthly invoices limit (default: 10000)",
                    "default": 10000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Business registered with the bulk-download provider.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rfc": {
                          "type": "string"
                        },
                        "legal_name": {
                          "type": "string"
                        },
                        "registered": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Business entity registered successfully",
                  "data": {
                    "rfc": "MEE200101ABC",
                    "legal_name": "MI EMPRESA EJEMPLO SA DE CV",
                    "registered": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request — FIEL not uploaded or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/schedule": {
      "get": {
        "operationId": "getInvoicesDownloadSchedule",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Get schedule configuration",
        "description": "Returns the current scheduled download configuration plus FIEL and registration status. Use this to check setup progress before configuring a schedule or submitting download requests.\n\n- `fiel_uploaded: true` — FIEL credentials are stored\n- `registered: true` — Business is registered with the SAT, downloads are enabled\n- `schedule` — Current schedule config, or `null` if not configured yet\n- `fiel` — FIEL certificate metadata (RFC, expiry, serial number)\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule configuration retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "fiel_uploaded": {
                          "type": "boolean",
                          "example": true
                        },
                        "registered": {
                          "type": "boolean",
                          "example": true
                        },
                        "registered_at": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Registration timestamp (ms)"
                        },
                        "sat_completed": {
                          "type": "boolean",
                          "description": "Whether the team has SAT invoicing (CSD) configured"
                        },
                        "fiel": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "rfc": {
                              "type": "string",
                              "example": "XAXX010101000"
                            },
                            "expires_at": {
                              "type": "integer",
                              "example": 1893456000000
                            },
                            "serial_number": {
                              "type": "string"
                            },
                            "uploaded_at": {
                              "type": "integer"
                            }
                          }
                        },
                        "schedule": {
                          "type": "object",
                          "nullable": true,
                          "properties": {
                            "enabled": {
                              "type": "boolean"
                            },
                            "time": {
                              "type": "string",
                              "example": "21:00"
                            },
                            "downloadTypes": {
                              "type": "array",
                              "items": {
                                "type": "string",
                                "enum": [
                                  "issued",
                                  "received"
                                ]
                              }
                            },
                            "daysBack": {
                              "type": "integer",
                              "example": 1
                            },
                            "lastRunAt": {
                              "type": "integer",
                              "nullable": true
                            },
                            "lastRunStatus": {
                              "type": "string",
                              "nullable": true
                            },
                            "lastRunError": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "schedule": {
                      "enabled": true,
                      "time": "06:00",
                      "downloadTypes": [
                        "received"
                      ],
                      "daysBack": 3,
                      "lastRunAt": 1767225600000,
                      "lastRunStatus": "success",
                      "lastRunError": null
                    },
                    "sat_completed": true,
                    "fiel_uploaded": true,
                    "registered": true,
                    "registered_at": 1767225600000,
                    "sync_start_date": "2021-01-01",
                    "fiel": {
                      "rfc": "MEE200101ABC",
                      "expires_at": 1893456000000,
                      "serial_number": "00001000000712345678",
                      "uploaded_at": 1767225600000
                    },
                    "prodigia": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "put": {
        "operationId": "updateInvoicesDownloadSchedule",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Save schedule configuration",
        "description": "Create or update the daily scheduled download. The schedule runs once per day at the specified time (America/Mexico_City timezone) and downloads invoices from the last `days_back` days.\n\n**Prerequisites:** FIEL must be uploaded and business must be registered. Returns `400` otherwise.\n\n**Warning:** If you include `issued` in `download_types` and your team already has SAT invoicing (CSD) configured, the response includes a `warning` field noting that issued invoices already exist in the system.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "enabled",
                  "time",
                  "download_types",
                  "days_back"
                ],
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "Enable or disable scheduled downloads"
                  },
                  "time": {
                    "type": "string",
                    "description": "Run time in HH:mm format (America/Mexico_City timezone)",
                    "example": "21:00"
                  },
                  "download_types": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "issued",
                        "received"
                      ]
                    },
                    "description": "Which invoice directions to download. Must be non-empty when `enabled` is true; may be an empty array when turning the schedule off",
                    "example": [
                      "received"
                    ]
                  },
                  "days_back": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 90,
                    "description": "How many days back to look on each run",
                    "example": 1
                  }
                }
              },
              "example": {
                "enabled": true,
                "time": "21:00",
                "download_types": [
                  "received"
                ],
                "days_back": 1
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Schedule saved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Scheduled download enabled successfully"
                    },
                    "warning": {
                      "type": "string",
                      "description": "Optional warning if issued invoices may be duplicated"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "schedule": {
                          "type": "object"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "schedule": {
                      "enabled": true,
                      "time": "06:00",
                      "downloadTypes": [
                        "received"
                      ],
                      "daysBack": 3,
                      "lastRunAt": 1767225600000,
                      "lastRunStatus": "success",
                      "lastRunError": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request — FIEL not uploaded, not registered, invalid time/types/days_back",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/schedule/history": {
      "get": {
        "operationId": "getInvoicesDownloadScheduleHistory",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Get download request history",
        "description": "Returns the last 20 download requests for your team, ordered by most recent first.\n\n**Live status check:** Any pending requests (`accepted`, `processing`, `pending`) are checked against the SAT in real time before the response is returned, so you always get up-to-date statuses in a single call.\n\n**Statuses:**\n| Status | Meaning |\n|--------|---------|\n| `pending` | Request queued, being sent to SAT |\n| `accepted` | SAT accepted the request, processing started |\n| `processing` | SAT is generating the package |\n| `completed` | Done — invoice metadata is available in the response |\n| `failed` | SAT rejected the request (see `statusMessage`) |\n| `expired` | Package expired before it was downloaded |\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "History retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "history": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "rfcType": {
                                "type": "string",
                                "enum": [
                                  "issued",
                                  "received"
                                ]
                              },
                              "startDate": {
                                "type": "string",
                                "format": "date"
                              },
                              "endDate": {
                                "type": "string",
                                "format": "date"
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "pending",
                                  "accepted",
                                  "processing",
                                  "completed",
                                  "failed",
                                  "expired"
                                ]
                              },
                              "invoiceCount": {
                                "type": "integer",
                                "description": "Total invoices found by SAT"
                              },
                              "processedCount": {
                                "type": "integer",
                                "description": "Invoices saved to sat_invoices"
                              },
                              "statusMessage": {
                                "type": "string",
                                "nullable": true
                              },
                              "source": {
                                "type": "string",
                                "enum": [
                                  "manual",
                                  "scheduled"
                                ]
                              },
                              "owner": {
                                "type": "string",
                                "nullable": true
                              },
                              "latestIssueDate": {
                                "type": "string",
                                "nullable": true
                              },
                              "earliestIssueDate": {
                                "type": "string",
                                "nullable": true
                              },
                              "createdAt": {
                                "type": "integer"
                              },
                              "completedAt": {
                                "type": "integer",
                                "nullable": true
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "history": [
                      {
                        "id": "satreq_Ab12Cd34",
                        "rfcType": "received",
                        "startDate": "2026-01-01",
                        "endDate": "2026-01-31",
                        "status": "completed",
                        "invoiceCount": 143,
                        "processedCount": 143,
                        "source": "manual",
                        "latestIssueDate": "2026-01-30",
                        "earliestIssueDate": "2026-01-02",
                        "createdAt": 1767225600000,
                        "completedAt": 1767312000000
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/progress": {
      "get": {
        "operationId": "getInvoicesDownloadProgress",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Get SAT history sync progress",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nReports how far the SAT has handed over your invoice history.\n\nThe SAT does not deliver a history all at once. It is backfilled forward from your sync start date in month-sized windows, and until that reaches the present, a query for a recent date range succeeds and returns nothing — identical to genuinely having no invoices. This endpoint is how you tell those apart.\n\n**Fields:**\n| Field | Meaning |\n|-------|---------|\n| `percent` | How much of the requested history has arrived |\n| `covered_through` | Last date the backfill has reached |\n| `months_remaining` | Roughly how much history is still pending |\n| `current` | History is close enough to the present to be usable |\n| `stalled` | Backfill has not advanced in over two days |\n| `enabled` | Sync is active. When `false` it will not advance on its own |\n| `eta_at` | Projected completion, epoch ms. Omitted while `stalled`, since a stopped sync has no meaningful estimate |\n\nValues are refreshed periodically in the background. Pass `refresh=true` to recompute against the provider, which takes a few seconds.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "refresh",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Recompute against the provider instead of serving the cached snapshot"
          }
        ],
        "responses": {
          "200": {
            "description": "Progress retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "registered": {
                          "type": "boolean",
                          "description": "False until FIEL credentials are connected"
                        },
                        "provider": {
                          "type": "object",
                          "nullable": true,
                          "description": "Null until the first background refresh has run",
                          "properties": {
                            "percent": {
                              "type": "number",
                              "example": 34.7
                            },
                            "covered_through": {
                              "type": "string",
                              "format": "date",
                              "example": "2022-10-13"
                            },
                            "months_remaining": {
                              "type": "number",
                              "example": 46.5
                            },
                            "current": {
                              "type": "boolean"
                            },
                            "stalled": {
                              "type": "boolean"
                            },
                            "enabled": {
                              "type": "boolean"
                            },
                            "eta_at": {
                              "type": "integer",
                              "nullable": true,
                              "description": "Projected completion, epoch ms. Omitted while stalled, since a stopped sync has no meaningful estimate"
                            },
                            "eta_confidence": {
                              "type": "string",
                              "nullable": true,
                              "enum": [
                                "observed",
                                "estimated",
                                null
                              ],
                              "description": "`observed` means the frontier was seen to move between two readings. `estimated` means it was averaged over everything covered since the sync began, which reads optimistically for an account that advanced early and then stopped"
                            },
                            "updated_at": {
                              "type": "integer"
                            }
                          }
                        },
                        "stored": {
                          "type": "object",
                          "nullable": true,
                          "description": "What we have saved so far, which lags the provider",
                          "properties": {
                            "total": {
                              "type": "integer"
                            }
                          }
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable explanation of the current state, in Spanish"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "registered": true,
                    "provider": {
                      "percent": 34.7,
                      "covered_through": "2022-10-13",
                      "months_remaining": 46.5,
                      "current": false,
                      "stalled": false,
                      "enabled": true,
                      "eta_at": 1790000000000,
                      "updated_at": 1767225600000
                    },
                    "stored": {
                      "total": 18234
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Team RFC not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/invoices/download/preview": {
      "post": {
        "operationId": "createInvoicesDownloadPreview",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Preview a range of SAT history before paying for it",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nQueues a metadata pull for a date range and reports how many CFDIs exist and what downloading them would cost.\n\nReading header data from the SAT costs nothing; only fetching an XML is billed. This endpoint uses that gap: it stores what it finds as browsable rows in the `metadata` stage, which you can list with `GET /invoices/sat?sync_state=metadata` and then selectively import.\n\nAnswers **202**, not 200. One month is roughly a twelve second round trip to the SAT and a full history is dozens of them, well past any HTTP timeout. Poll `GET /invoices/download/jobs/{id}` for progress.\n\nOnly one job may run per team at a time.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "start_date",
                  "end_date"
                ],
                "properties": {
                  "start_date": {
                    "type": "string",
                    "format": "date",
                    "example": "2026-01-01"
                  },
                  "end_date": {
                    "type": "string",
                    "format": "date",
                    "example": "2026-08-31"
                  },
                  "directions": {
                    "type": "array",
                    "description": "Defaults to received only",
                    "items": {
                      "type": "string",
                      "enum": [
                        "issued",
                        "received"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job queued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "example": "satjob_a1b2c3d4e5"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "queued"
                          ]
                        },
                        "total_windows": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Sincronización encolada",
                  "data": {
                    "id": "satjob_a1b2c3d4e5",
                    "status": "queued",
                    "total_windows": 8
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid date range or directions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Descarga Masiva not activated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A job is already running for this team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/invoices/download/jobs": {
      "get": {
        "operationId": "listInvoicesDownloadJobs",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "List recent preview and import jobs",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nThe last 20 jobs for your team, newest first, each with its progress and cost estimate.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Jobs retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "jobs": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/SatImportJobSummary"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "jobs": [
                      {
                        "id": "satjob_a1b2c3d4e5",
                        "type": "preview",
                        "status": "running",
                        "params": {
                          "startDate": "2026-01-01",
                          "endDate": "2026-08-31",
                          "directions": [
                            "received"
                          ]
                        },
                        "progress": {
                          "totalWindows": 8,
                          "doneWindows": 3,
                          "invoicesFound": 412,
                          "invoicesSaved": 412,
                          "alreadyInGigstack": 0
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/invoices/download/jobs/{id}": {
      "get": {
        "operationId": "getInvoicesDownloadJob",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Get one job with per-window detail",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nSame shape as the list, plus the individual month windows and their state. Useful for showing which part of a long history pull is still outstanding.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/SatImportJobSummary"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "windows": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "key": {
                                    "type": "string"
                                  },
                                  "start": {
                                    "type": "string",
                                    "format": "date"
                                  },
                                  "end": {
                                    "type": "string",
                                    "format": "date"
                                  },
                                  "direction": {
                                    "type": "string",
                                    "enum": [
                                      "issued",
                                      "received"
                                    ]
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "pending",
                                      "requested",
                                      "done",
                                      "error"
                                    ]
                                  },
                                  "foundCount": {
                                    "type": "integer"
                                  },
                                  "savedCount": {
                                    "type": "integer"
                                  },
                                  "error": {
                                    "type": "string",
                                    "nullable": true
                                  }
                                }
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "satjob_a1b2c3d4e5",
                    "type": "preview",
                    "status": "running",
                    "params": {
                      "startDate": "2026-01-01",
                      "endDate": "2026-08-31",
                      "directions": [
                        "received"
                      ]
                    },
                    "progress": {
                      "totalWindows": 8,
                      "doneWindows": 3,
                      "invoicesFound": 412,
                      "invoicesSaved": 412,
                      "alreadyInGigstack": 0
                    },
                    "windows": [
                      {
                        "key": "2026-01-received",
                        "start": "2026-01-01",
                        "end": "2026-01-31",
                        "direction": "received",
                        "status": "done",
                        "foundCount": 57,
                        "savedCount": 57,
                        "error": null
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Job not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/invoices/download/jobs/{id}/cancel": {
      "post": {
        "operationId": "cancelInvoicesDownloadJob",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Stop a running job",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nMarks the job cancelled. The worker checks between windows, so it stops after finishing the one in flight rather than immediately. Already-completed jobs are returned unchanged.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "satjob_a1b2c3d4e5",
                    "status": "cancelled"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Job not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/invoices/download/import": {
      "post": {
        "operationId": "importInvoicesDownload",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Download XMLs for chosen CFDIs",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\n**This is the billed call.** Each XML costs $0.20 MXN, charged once per CFDI.\n\nTakes UUIDs that are currently in the `metadata` stage — typically ones you found via a preview and `GET /invoices/sat?sync_state=metadata` — and queues their XML download.\n\n**Cost confirmation.** The server always recomputes the cost; `confirm_cost_mxn` is only ever checked against it, never trusted. Send it and a mismatch returns **409** rather than charging a different amount than you were shown. Omit it and the call is allowed only up to 100 invoices; past that confirmation is required, so a large import cannot happen by accident.\n\nAnything not importable is reported in `skipped` with a reason rather than failing the call: `not_found`, `wrong_team`, `already_imported`, `already_queued`, `is_nomina` (nómina XMLs carry employee PII and are never downloadable), `not_importable`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "uuids"
                ],
                "properties": {
                  "uuids": {
                    "type": "array",
                    "maxItems": 500,
                    "items": {
                      "type": "string"
                    }
                  },
                  "confirm_cost_mxn": {
                    "type": "number",
                    "description": "Cost you expect to be charged. Required above 100 invoices.",
                    "example": 12.4
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoices queued for download",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "queued": {
                          "type": "integer"
                        },
                        "estimated_cost_mxn": {
                          "type": "number"
                        },
                        "skipped": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "uuid": {
                                "type": "string"
                              },
                              "reason": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "2 facturas en cola de descarga",
                  "data": {
                    "queued": 2,
                    "estimated_cost_mxn": 0.4,
                    "skipped": [
                      {
                        "uuid": "A1B2C3D4-E5F6-7890-ABCD-1234567890AB",
                        "reason": "already_imported"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing uuids or over the per-call limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Descarga Masiva not activated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Cost confirmation required or mismatched",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/invoices/download/request": {
      "post": {
        "operationId": "createInvoicesDownloadRequest",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Create bulk download request",
        "description": "Submit a bulk download request to the SAT. The SAT processes these asynchronously — use `GET /invoices/download/schedule/history` to poll for status updates.\n\n**Prerequisites:** FIEL uploaded (`fiel_uploaded: true`) + business registered (`registered: true`) + Descarga Masiva activated.\n\n**Date range:** SAT limits each request to a maximum of 1 month. For longer periods, submit one request per month.\n\nOnce the request reaches `completed` status, the invoice metadata is available in the history response (`invoiceCount`, `processedCount`, `latestIssueDate`, `earliestIssueDate`).\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "start_date",
                  "end_date"
                ],
                "properties": {
                  "start_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Start of date range (YYYY-MM-DD)",
                    "example": "2024-01-01"
                  },
                  "end_date": {
                    "type": "string",
                    "format": "date",
                    "description": "End of date range (YYYY-MM-DD)",
                    "example": "2024-01-31"
                  },
                  "rfc_type": {
                    "type": "string",
                    "enum": [
                      "issued",
                      "received"
                    ],
                    "description": "Direction of invoices to download (default: received)",
                    "default": "received"
                  },
                  "request_type": {
                    "type": "string",
                    "enum": [
                      "cfdi",
                      "metadata"
                    ],
                    "description": "Download XML files (cfdi) or metadata only (default: cfdi)",
                    "default": "cfdi"
                  },
                  "invoice_type": {
                    "type": "string",
                    "enum": [
                      "I",
                      "E",
                      "P",
                      "N",
                      "T"
                    ],
                    "description": "Filter by CFDI type: I=income, E=expense, P=payment, N=payroll, T=transfer"
                  },
                  "invoice_status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "cancelled",
                      "all"
                    ],
                    "description": "Filter by invoice status (default: all)"
                  },
                  "third_party_rfc": {
                    "type": "string",
                    "description": "Filter by counterparty RFC"
                  },
                  "min_amount": {
                    "type": "string",
                    "description": "Minimum invoice amount"
                  },
                  "max_amount": {
                    "type": "string",
                    "description": "Maximum invoice amount"
                  }
                }
              },
              "example": {
                "start_date": "2024-01-01",
                "end_date": "2024-01-31",
                "rfc_type": "received"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Requests created, one per calendar month of the range. Already-pending months are reported in `duplicates` instead of being submitted again.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "created": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Ids of the requests created (use with `GET /invoices/download/status/{request_id}`)."
                        },
                        "duplicates": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Ids of identical requests already pending."
                        },
                        "chunks": {
                          "type": "integer",
                          "description": "Number of monthly periods the range was split into."
                        },
                        "duplicate": {
                          "type": "boolean",
                          "description": "`true` when every period already had a pending request."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "2 solicitud(es) creada(s) para 2 período(s) mensual(es)",
                  "data": {
                    "created": [
                      "satreq_Ab12Cd34",
                      "satreq_Ef56Gh78"
                    ],
                    "duplicates": [],
                    "chunks": 2,
                    "duplicate": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request — FIEL not uploaded, not registered, or billing not activated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Descarga Masiva is not activated for the team (`error: billing_not_activated`) — call\n`POST /invoices/download/activate` first. Raw body, not the standardized envelope. An\nauthentication-layer `403` (see `AuthForbidden`) is also possible.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "message": "Descarga Masiva is not activated for this team. Activate it first using POST /v2/invoices/download/activate.",
                  "error": "billing_not_activated"
                }
              }
            }
          },
          "429": {
            "description": "Daily limit reached: at most **10 manual download requests per team per calendar day**\n(America/Mexico_City). The counter resets at midnight Mexico City time. Raw body, not the\nstandardized envelope; no `Retry-After` header is sent.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "error": {
                      "type": "string",
                      "enum": [
                        "rate_limit_exceeded"
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "limit": {
                          "type": "integer"
                        },
                        "resets_at": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": false,
                  "message": "Daily limit reached. You can submit up to 10 manual download requests per day. Resets at midnight Mexico City time.",
                  "error": "rate_limit_exceeded",
                  "data": {
                    "limit": 10,
                    "resets_at": "midnight America/Mexico_City"
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/status/{request_id}": {
      "get": {
        "operationId": "getInvoicesDownloadStatusByRequestId",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Check download request status",
        "description": "Check the current SAT processing status of a download request (an id from the `created` array of\n`POST /invoices/download/request`).\n\nWhen `status` is `completed`, `packages` lists the packages to download with\n`GET /invoices/download/package/{package_id}`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "request_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Request ID returned from POST /invoices/download/request",
            "example": "req_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Current SAT status. Download each entry of `packages` with `GET /invoices/download/package/{package_id}`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "gigstack request id"
                        },
                        "request_id": {
                          "type": "string",
                          "description": "Provider request id"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "pending",
                            "accepted",
                            "processing",
                            "completed",
                            "failed",
                            "expired"
                          ]
                        },
                        "status_code": {
                          "type": "string"
                        },
                        "invoice_count": {
                          "type": "integer"
                        },
                        "invoices_saved": {
                          "type": "integer",
                          "description": "Present once invoices were stored."
                        },
                        "invoices": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "packages": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "index": {
                                "type": "integer"
                              }
                            }
                          }
                        },
                        "message": {
                          "type": "string",
                          "nullable": true
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Status retrieved successfully",
                  "data": {
                    "id": "satreq_Ab12Cd34",
                    "request_id": "9f1c2a3b-4d5e-6f70-8192-a3b4c5d6e7f8",
                    "status": "completed",
                    "status_code": "5000",
                    "invoice_count": 143,
                    "invoices_saved": 143,
                    "invoices": [],
                    "packages": [
                      {
                        "id": "9F1C2A3B-4D5E-6F70-8192-A3B4C5D6E7F8_01",
                        "index": 1
                      }
                    ],
                    "message": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/package/{package_id}": {
      "get": {
        "operationId": "getInvoicesDownloadPackageByPackageId",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Download XML package",
        "description": "Download a package of XML files for a completed download request. Package ids come from `packages[].id`\nin `GET /invoices/download/status/{request_id}`.\n\nThe ZIP is returned **base64-encoded inside JSON** (`data.content`), not as a binary response. Packages\nexpire after a period set by the SAT — download them promptly.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "package_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Package ID from the status response",
            "example": "pkg_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "The package, as **base64** inside a JSON body (not a binary download).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "package_id": {
                          "type": "string"
                        },
                        "content": {
                          "type": "string",
                          "description": "Base64-encoded ZIP of the XML files."
                        },
                        "content_type": {
                          "type": "string",
                          "enum": [
                            "application/zip"
                          ]
                        },
                        "encoding": {
                          "type": "string",
                          "enum": [
                            "base64"
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Package downloaded successfully",
                  "data": {
                    "package_id": "9F1C2A3B-4D5E-6F70-8192-A3B4C5D6E7F8_01",
                    "content": "UEsDBBQAAAAIAA...",
                    "content_type": "application/zip",
                    "encoding": "base64"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/invoice/{uuid}": {
      "get": {
        "operationId": "getInvoicesDownloadInvoiceByUuid",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Get single invoice from SAT",
        "description": "Fetch a single invoice's XML from the SAT by UUID. Useful for retrieving a specific CFDI without submitting a full bulk download request.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "CFDI UUID (folio fiscal)",
            "example": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e"
          }
        ],
        "responses": {
          "200": {
            "description": "The CFDI XML, base64-encoded. `cached: true` when served from gigstack's copy.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "uuid": {
                          "type": "string"
                        },
                        "xml_base64": {
                          "type": "string"
                        },
                        "cached": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Invoice retrieved successfully",
                  "data": {
                    "uuid": "6741A863-04BE-49FE-BB76-E1657AB6B7EA",
                    "xml_base64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4K...",
                    "cached": false
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/debug": {
      "get": {
        "operationId": "getInvoicesDownloadDebug",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Debug registration status",
        "description": "Returns detailed debug information about your team's Descarga Masiva setup: FIEL status, registration status, schedule config, and SAT connectivity. Intended for troubleshooting.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Debug info retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Debug info retrieved",
                  "data": {
                    "team_rfc": "MEE200101ABC",
                    "registered_business": null,
                    "sat_requests": []
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/invoices/download/enable-sync": {
      "post": {
        "operationId": "createInvoicesDownloadEnableSync",
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Enable SAT sync",
        "description": "Enables automatic SAT synchronization for your team. This is a lower-level toggle — in most flows the schedule configuration (`PUT /invoices/download/schedule`) is the right endpoint to use.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Automatic sync enabled.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rfc": {
                          "type": "string"
                        },
                        "sync_enabled": {
                          "type": "boolean"
                        },
                        "api_message": {
                          "type": "string",
                          "description": "Message from the provider."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "SAT sync enabled successfully",
                  "data": {
                    "rfc": "MEE200101ABC",
                    "sync_enabled": true
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/payments/{id}": {
      "get": {
        "operationId": "getPaymentsById",
        "tags": [
          "Payments"
        ],
        "summary": "Get payment",
        "description": "Retrieve a specific payment by ID.\n\n**gigstack Connect:** Access other teams' payments using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "payment_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "payment_1234567890",
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "emails": [
                      "contabilidad@ejemplo.com"
                    ],
                    "currency": "MXN",
                    "allowed_payment_methods": [
                      "card",
                      "bank"
                    ],
                    "exchange_rate": 1,
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicios de consultoría profesional",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48",
                        "unit_name": "Unidad de servicio",
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false
                          }
                        ],
                        "team": "team_1234567890",
                        "created_at": 1767225600000,
                        "from": "api"
                      }
                    ],
                    "metadata": {},
                    "team": "team_1234567890",
                    "idempotency_key": "payment-2026-0001",
                    "from": "api",
                    "invoices": [
                      "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
                    ],
                    "livemode": true,
                    "owner": "user_1234567890",
                    "payment_form": "03",
                    "payments": [],
                    "receipts": [],
                    "refunds": [],
                    "short_url": "https://gigstack.xyz/Xk3mP9",
                    "success_url": null,
                    "status": "succeeded",
                    "total": 1160,
                    "total_refunded": 0,
                    "subtotal": 1000,
                    "taxes": 160,
                    "discount": 0,
                    "withholding_taxes": 0,
                    "created_at": 1767225600000,
                    "succeeded_at": 1767225900000,
                    "payment_processor": "api"
                  },
                  "message": "Payment retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "put": {
        "operationId": "updatePaymentsById",
        "tags": [
          "Payments"
        ],
        "summary": "Update payment",
        "description": "Update a payment. The endpoint supports modifying the `description` of items, attaching `automation_type` to a payment that has no automations, and patching the embedded `client` (with the change propagated to the `/clients/{id}` master record). The body must include at least one of `items`, `automation_type` or `client`.\n\n**gigstack Connect:** Update other teams' payments using the `team` parameter.\n\n## What can be updated\n\n- **Item description**: For each entry in `items`, the item is matched by `id` inside the payment and its `description` is replaced. Any other field on the item (taxes, discounts, quantity, unit_price, etc.) is rejected by validation. Item totals, taxes and `itemsAmounts` are not recalculated.\n- **Automations**: `automation_type` is only accepted when the payment has no existing automations. If the payment already has automations, the request returns 400. The same enum values used by `POST /payments/register` apply (`pue_invoice`, `ppd_invoice_and_complement`, `none`).\n- **Client**: The `client` object accepts a partial patch (`name`, `company`, `phone`, `email`, `bcc`, `metadata`, `legal_name`, `tax_id`, `use`, `tax_system`, `address`). The client `id` cannot be modified. Each provided field is written both to the `client` embedded in the payment and to the `/clients/{id}` master document via a partial merge. Fiscal/SAT validation is not re-run from this endpoint — call `PUT /clients/{id}` if full re-validation is needed.\n\n## Trigger re-fire for already succeeded payments\n\nWhen non-empty automations are added (i.e. `automation_type` is `pue_invoice` or `ppd_invoice_and_complement`) and the payment is already `succeeded`, the endpoint performs a second write that sets `status` to `succeeded_` so that the downstream automation trigger (which fires on transitions into `succeeded`) can re-fire on a subsequent flip back to `succeeded`.\n\n## Allowed payment statuses\n\nThe endpoint accepts updates regardless of payment status (including `succeeded` and `cancelled`) so descriptions can be corrected after the fact. Note that this endpoint does not re-issue or modify any CFDI already linked to the payment.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "payment_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePaymentInput"
              },
              "examples": {
                "update_item_description": {
                  "summary": "Fix the description of one item",
                  "value": {
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicio de consultoría profesional - corregido"
                      }
                    ]
                  }
                },
                "add_automation": {
                  "summary": "Attach a PUE invoice automation to a payment that had none",
                  "value": {
                    "automation_type": "pue_invoice"
                  }
                },
                "update_both": {
                  "summary": "Update item description and add automations in a single call",
                  "value": {
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicio de consultoría profesional - corregido"
                      }
                    ],
                    "automation_type": "pue_invoice"
                  }
                },
                "update_client_email": {
                  "summary": "Update only the email of the client",
                  "value": {
                    "client": {
                      "email": "nuevo.correo@ejemplo.com"
                    }
                  }
                },
                "update_client_fiscal": {
                  "summary": "Update fiscal info and address of the client",
                  "value": {
                    "client": {
                      "legal_name": "JUAN PEREZ GARCIA",
                      "tax_id": "PEGJ800101ABC",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "country": "MEX",
                        "zip": "06600",
                        "state": "CDMX"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "payment_1234567890",
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "emails": [
                      "contabilidad@ejemplo.com"
                    ],
                    "currency": "MXN",
                    "allowed_payment_methods": [
                      "card",
                      "bank"
                    ],
                    "exchange_rate": 1,
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicios de consultoría profesional",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48",
                        "unit_name": "Unidad de servicio",
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false
                          }
                        ],
                        "team": "team_1234567890",
                        "created_at": 1767225600000,
                        "from": "api"
                      }
                    ],
                    "metadata": {},
                    "team": "team_1234567890",
                    "idempotency_key": "payment-2026-0001",
                    "from": "api",
                    "invoices": [
                      "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
                    ],
                    "livemode": true,
                    "owner": "user_1234567890",
                    "payment_form": "03",
                    "payments": [],
                    "receipts": [],
                    "refunds": [],
                    "short_url": "https://gigstack.xyz/Xk3mP9",
                    "success_url": null,
                    "status": "succeeded",
                    "total": 1160,
                    "total_refunded": 0,
                    "subtotal": 1000,
                    "taxes": 160,
                    "discount": 0,
                    "withholding_taxes": 0,
                    "created_at": 1767225600000,
                    "succeeded_at": 1767225900000,
                    "payment_processor": "api"
                  },
                  "message": "Payment updated successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Validation error. Possible causes: empty body, item id not found in payment, payment already has automations, or unexpected fields on items.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The authenticated team does not own this payment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Payment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deletePaymentsById",
        "tags": [
          "Payments"
        ],
        "summary": "Cancel payment",
        "description": "Cancel a specific payment.\n\n**gigstack Connect:** Cancel other teams' payments using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "payment_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment cancelled successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "payment_1234567890",
                    "status": "canceled",
                    "cancelled_at": 1767225600000
                  },
                  "message": "Payment cancelled successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/payments/request": {
      "post": {
        "operationId": "createPaymentsRequest",
        "tags": [
          "Payments"
        ],
        "summary": "Request payment",
        "description": "Create a payment request that creates a payment in 'requires_payment_method' status.\n\n**gigstack Connect:** Create payment requests for other teams using the `team` parameter.\n\n## Payment Request Flow\n\nThis endpoint creates a payment request that customers can complete using various payment methods.\nThe payment will be created with status 'requires_payment_method'.\n\n## Allowed Payment Methods\n\n`allowed_payment_methods` is required. The validator accepts exactly these five values:\n\n- **`card`** — credit/debit card\n- **`bank`** — Mexican bank transfer (SPEI)\n- **`oxxo`** — OXXO convenience store\n- **`stripe-spei`** — Stripe customer balance\n- **`mercadopago-wallet`** — Mercado Pago wallet\n\nThe handler then narrows the list per processor and rejects anything outside the\nprocessor's own set:\n\n| `payment_processor` | accepted methods | currency |\n|---|---|---|\n| `stripe` (default) | `card`, `oxxo`, `bank`, `stripe-spei` | any |\n| `mercadopago` | `card`, `oxxo`, `mercadopago-wallet` | `MXN` only |\n| `openpay` | `card`, `bank_account`, `store` | `MXN` only |\n| `pagoralia` | `hosted`, `card`, `oxxo` | `MXN` only |\n| `conekta` | `hosted`, `card`, `oxxo`, `spei` | `MXN` only |\n\n> The processor-specific names in the right-hand column (`bank_account`, `store`,\n> `hosted`, `spei`) are **not** accepted by body validation — only the five enum values\n> above pass, so those processors are effectively limited to their overlap with the enum.\n\n## Required fields\n\n`client`, `currency`, `allowed_payment_methods`, `items` and **`automation_type`** are\nall required. `automation_type` has no default: omitting it fails validation with\n`missing_required`. Allowed values: `pue_invoice`, `ppd_invoice_and_complement`, `none`.\n\n## Email suppression\n\n`ignore_emails` takes precedence over `send_email`: the handler stores\n`ignore_emails ?? (send_email === false)`, so `ignore_emails: true` suppresses\nnotifications regardless of `send_email`.\n\n## Unknown fields\n\nBody validation runs in strict allowlist mode — any key not declared in the schema is\nrejected with `400 validation_failed` / `unexpected_key`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RequestPaymentInput"
              },
              "example": {
                "client": {
                  "id": "client_1234567890"
                },
                "automation_type": "pue_invoice",
                "currency": "MXN",
                "exchange_rate": 1,
                "allowed_payment_methods": [
                  "card",
                  "bank",
                  "oxxo"
                ],
                "items": [
                  {
                    "id": "service_1234567890",
                    "quantity": 1,
                    "unit_price": 1000
                  }
                ],
                "send_email": true,
                "emails": [
                  "customer@example.com"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment request created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Payment request created successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicPayment"
                    }
                  }
                },
                "example": {
                  "message": "Payment request created successfully",
                  "data": {
                    "id": "payment_1234567890",
                    "client": {
                      "id": "client_1234567890",
                      "name": "Juan Pérez García",
                      "email": "juan.perez@ejemplo.com",
                      "tax_id": "PEGJ800101ABC",
                      "from": "api",
                      "livemode": true,
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "status": "requires_payment_method",
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "allowed_payment_methods": [
                      {
                        "id": "card"
                      },
                      {
                        "id": "bank"
                      },
                      {
                        "id": "oxxo"
                      }
                    ],
                    "short_url": "https://gigstack.xyz/Xk3mP9",
                    "total": 1160,
                    "subtotal": 1000,
                    "taxes": 160,
                    "discount": 0,
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Professional consulting services",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      }
                    ],
                    "emails": [
                      "customer@example.com"
                    ],
                    "created_at": 1677651234,
                    "payment_processor": "api",
                    "livemode": true,
                    "team": "team_1234567890",
                    "owner": "user_1234567890",
                    "from": "api",
                    "refunds": [],
                    "total_refunded": 0,
                    "withholding_taxes": 0,
                    "succeeded_at": 1767225600000,
                    "payment_form": "",
                    "idempotency_key": "",
                    "invoices": [],
                    "payments": [],
                    "receipts": []
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request — `validation_failed` (missing `automation_type`, a method outside the\nenum, or an unknown key) or `invalid_request_body` (method not supported by the\nselected processor, non-`MXN` currency on a MXN-only processor, `Invalid automation type`).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Referenced client or service belongs to another team, or `livemode` mismatch.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Referenced client or service id was not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key` already used (`error.code: resource_conflict`), or a concurrent create holds the client/service lock — retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/payments/register": {
      "post": {
        "operationId": "createPaymentsRegister",
        "tags": [
          "Payments"
        ],
        "summary": "Register payment",
        "description": "[Small working example](/recipes/payment)\n\n**Integration note:** Records money already received; does not charge a card. Repeating a creation idempotency_key returned HTTP 400 with error.code resource_conflict in staging. Reconcile the existing payment. ppd_invoice_id is a SAT UUID and enables complement automation even with automation_type none. Registration success is not proof that the asynchronous complement finished.\n\nRegister a payment with optional automation for invoice creation.\n\n**gigstack Connect:** Register payments for other teams using the `team` parameter.\n\n## Automation Types\n\nControl what happens automatically when registering a payment:\n\n- **`pue_invoice`**: Creates a PUE (Pago en Una sola Exhibición) invoice immediately\n- **`none`**: No automation, registers payment only\n\n## PPD Invoice Linking\n\nYou can link a payment to an existing PPD (Pago en Parcialidades o Diferido) invoice by providing the `ppd_invoice_id` field.\nWhen set, a payment complement (complemento de pago) CFDI will be automatically generated and linked to the PPD invoice.\nThe referenced invoice must have `payment_method='PPD'` and `status='valid'`.\n\n## Payment Form\n\nThe `payment_form` field specifies the Mexican SAT payment form code:\n\nCommon codes include: `01` (cash), `02` (check), `03` (electronic transfer), `04` (credit card), etc.\n\nThe payment will be marked as 'succeeded' immediately upon registration.\n\n## Required fields\n\n`client`, `currency`, `items` (at least one), `payment_form` and **`automation_type`**\nare required. `automation_type` has no default — omitting it fails validation.\nAllowed values: `pue_invoice`, `ppd_invoice_and_complement`, `none`.\n\n## `date`\n\nOptional, in **Unix epoch milliseconds** (13 digits). Compared against\n`Luxon.now().toMillis()`; a future value returns `400`.\n\n## `transfer_data` — all-or-nothing\n\n`transfer_data` is optional, but **when it is present all four of `master`, `connect`,\n`master_to` and `connect_to` are required**; omitting any one fails validation.\n\n| field | type | constraint |\n|---|---|---|\n| `master` | number | required, `0 ≤ master ≤ 100` (percentage retained by the master team) |\n| `connect` | string | required, non-empty — RFC of the connected team |\n| `master_to` | enum | required — `client` or `connect` |\n| `connect_to` | enum | required — `client` or `master` |\n| `connect_custom_config` | object | optional; every field inside it is optional except `type`, `rate` and `withholding` on each `taxes[]` entry |\n\n## `invoice_config`\n\nAll nested fields are optional:\n\n| field | type | meaning |\n|---|---|---|\n| `serie` | string | invoice series |\n| `folio` | number | invoice folio number |\n| `date` | number | invoice issue date, Unix epoch **milliseconds** |\n| `global.year` | number | fiscal year of the global (EOM) invoice, e.g. `2026` |\n| `global.months` | string | SAT `c_Meses` code, e.g. `01` for January or `13` for Jan–Feb |\n| `global.periodicity` | string | SAT `c_Periodicidad` code — `01` daily, `02` weekly, `03` fortnightly, `04` monthly, `05` bimonthly |\n| `validUntil` | number | expiry of the self-invoicing window, Unix epoch **milliseconds** |\n\n## Email suppression\n\n`ignore_emails: true` suppresses notification emails. On this endpoint `send_email` is\naccepted but has no effect — only `ignore_emails` is persisted onto the payment.\n\n## Unknown fields\n\nBody validation runs in strict allowlist mode — any undeclared key is rejected with\n`400 validation_failed` / `unexpected_key`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterPaymentInput"
              },
              "examples": {
                "standard_payment": {
                  "summary": "Standard payment without splitting",
                  "value": {
                    "client": {
                      "id": "client_1234567890"
                    },
                    "automation_type": "pue_invoice",
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "payment_form": "03",
                    "items": [
                      {
                        "id": "service_1234567890",
                        "quantity": 1,
                        "unit_price": 1000
                      }
                    ]
                  }
                },
                "percentage_split": {
                  "summary": "Payment with percentage-based splitting",
                  "value": {
                    "client": {
                      "id": "client_1234567890"
                    },
                    "automation_type": "pue_invoice",
                    "currency": "MXN",
                    "payment_form": "03",
                    "items": [
                      {
                        "id": "service_1234567890",
                        "quantity": 1,
                        "unit_price": 1000
                      }
                    ],
                    "transfer_data": {
                      "master": 30,
                      "connect": "EMP800101ABC",
                      "master_to": "client",
                      "connect_to": "master"
                    }
                  }
                },
                "ppd_complement": {
                  "summary": "Payment linked to an existing PPD invoice",
                  "description": "Register a payment and automatically generate a payment complement (complemento de pago) linked to an existing PPD invoice",
                  "value": {
                    "client": {
                      "id": "client_1234567890"
                    },
                    "automation_type": "none",
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "payment_form": "03",
                    "ppd_invoice_id": "invoice_ppd_1234567890",
                    "items": [
                      {
                        "id": "service_1234567890",
                        "quantity": 1,
                        "unit_price": 1000
                      }
                    ]
                  }
                },
                "fixed_commission": {
                  "summary": "Payment with fixed commission fee",
                  "description": "Use custom_price to charge a fixed commission instead of percentage",
                  "value": {
                    "client": {
                      "id": "client_1234567890"
                    },
                    "automation_type": "pue_invoice",
                    "currency": "MXN",
                    "payment_form": "03",
                    "items": [
                      {
                        "id": "service_1234567890",
                        "quantity": 1,
                        "unit_price": 1000
                      }
                    ],
                    "transfer_data": {
                      "master": 0,
                      "connect": "EMP800101ABC",
                      "master_to": "client",
                      "connect_to": "master",
                      "connect_custom_config": {
                        "custom_price": 50,
                        "custom_description": "Platform service fee"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Payment registered successfully. **Both** the standard path and the\n`transfer_data` split path return `201` with the standardized success envelope.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string",
                          "description": "`Payment registered successfully` on the standard path, `Split payments registered successfully` on the split path.",
                          "example": "Payment registered successfully"
                        },
                        "data": {
                          "oneOf": [
                            {
                              "$ref": "#/components/schemas/ApiPublicPayment"
                            },
                            {
                              "type": "object",
                              "description": "Split payment result (returned when `transfer_data` is present)",
                              "properties": {
                                "split_reference": {
                                  "type": "string",
                                  "example": "split_abc123xyz"
                                },
                                "master_payment_id": {
                                  "type": "string",
                                  "example": "payment_master_123"
                                },
                                "connect_payment_id": {
                                  "type": "string",
                                  "example": "payment_connect_456"
                                },
                                "master_amount": {
                                  "type": "number",
                                  "example": 696
                                },
                                "connect_amount": {
                                  "type": "number",
                                  "example": 464
                                },
                                "total_amount": {
                                  "type": "number",
                                  "example": 1160
                                },
                                "master_payment": {
                                  "type": "object"
                                },
                                "connect_payment": {
                                  "type": "object"
                                },
                                "connect_team": {
                                  "type": "object",
                                  "nullable": true,
                                  "properties": {
                                    "id": {
                                      "type": "string"
                                    },
                                    "tax_id": {
                                      "type": "string"
                                    },
                                    "legal_name": {
                                      "type": "string"
                                    },
                                    "is_newly_created": {
                                      "type": "boolean"
                                    },
                                    "onboarding_url": {
                                      "type": "string"
                                    }
                                  }
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "standard_payment": {
                    "summary": "Standard payment response",
                    "value": {
                      "success": true,
                      "message": "Payment registered successfully",
                      "timestamp": 1767225600000,
                      "data": {
                        "id": "payment_1234567890",
                        "client": {
                          "id": "client_1234567890",
                          "name": "Juan Pérez García",
                          "email": "juan.perez@ejemplo.com",
                          "tax_id": "PEGJ800101ABC"
                        },
                        "status": "succeeded",
                        "currency": "MXN",
                        "exchange_rate": 1,
                        "payment_form": "03",
                        "total": 1160,
                        "subtotal": 1000,
                        "taxes": 160,
                        "discount": 0,
                        "items": [
                          {
                            "id": "service_1234567890",
                            "description": "Professional consulting services",
                            "quantity": 1,
                            "unit_price": 1000,
                            "product_key": "80141503",
                            "unit_key": "E48"
                          }
                        ],
                        "invoices": [
                          "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
                        ],
                        "created_at": 1677651234,
                        "succeeded_at": 1677651234,
                        "payment_processor": "api",
                        "livemode": true,
                        "team": "team_1234567890",
                        "owner": "user_1234567890"
                      }
                    }
                  },
                  "split_payment": {
                    "summary": "Split payment response",
                    "description": "Response when using transfer_data to split payments",
                    "value": {
                      "success": true,
                      "message": "Split payments registered successfully",
                      "timestamp": 1767225600000,
                      "data": {
                        "split_reference": "split_abc123xyz",
                        "master_payment_id": "payment_master_123",
                        "connect_payment_id": "payment_connect_456",
                        "master_amount": 696,
                        "connect_amount": 464,
                        "total_amount": 1160,
                        "master_payment": {
                          "id": "payment_master_123",
                          "client": "client_1234567890",
                          "amount": 696,
                          "team": "team_master_123",
                          "split_role": "master"
                        },
                        "connect_payment": {
                          "id": "payment_connect_456",
                          "client": "client_connect_789",
                          "amount": 464,
                          "team": "team_connect_456",
                          "split_role": "connect"
                        },
                        "connect_team": {
                          "id": "team_connect_456",
                          "tax_id": "EMP800101ABC",
                          "legal_name": "Empresa Ejemplo SA de CV",
                          "is_newly_created": true,
                          "onboarding_url": "https://embeded.gigstack.pro/?sessionId=otpOnboarding_7Kd2Pq&c=193847"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request. Emitted with `error.code`:\n- `validation_failed` — body failed schema validation (missing required field,\n  bad enum value, or an unknown key: the validator rejects fields it does not declare).\n- `invalid_request_body` — `Invalid automation type`, `PPD invoice not found with uuid: …`,\n  `The referenced invoice is not valid (stamped)`, `Payment date cannot be in the future`,\n  or `Exchange rate not found for the specified currency`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — the referenced client or service belongs to another team, or its\n`livemode` does not match the API key. Raised by resource resolution with\n`error.code: resource_resolution_failed`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Referenced client or service id was not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — the supplied `idempotency_key` has already been used\n(`error.code: resource_conflict`, message `Idempotency key error`). On the split\npath either the master or the connect payment can trigger this. Resource\nresolution also returns 409 when a concurrent create for the same client/service\nholds the lock; retry the request.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/payments/{id}/paid": {
      "post": {
        "operationId": "createPaymentsByIdPaid",
        "tags": [
          "Payments"
        ],
        "summary": "Mark payment as paid",
        "description": "Mark a payment as paid with the specified payment form.\n\n**gigstack Connect:** Mark other teams' payments as paid using the `team` parameter.\n\n## Required Information\n- **payment_form** (required): SAT-compliant payment form code (`01`–`31`, `99`)\n- **date** (optional): when the payment was received, in **Unix epoch milliseconds**\n  (13 digits). The handler passes the value straight to `Luxon.fromMillis()` and\n  compares it against `Luxon.now().toMillis()`; a seconds-based timestamp resolves to\n  1970 and is silently accepted. Defaults to now. A future date returns `400`.\n- **send_email** / **ignore_emails** (optional): `ignore_emails` takes precedence —\n  the handler resolves `ignore_emails ?? (send_email === false)`, so `ignore_emails: true`\n  suppresses notifications even when `send_email: true`.\n- **amount_received** (optional): cumulative amount received so far, in the payment's\n  currency. Omit it, or send the full payment amount, to mark the payment `succeeded`\n  (unchanged default behavior). Send less than the full amount to record a partial\n  top-up: the payment is set to `partially_paid` instead, triggering a partial payment\n  complement on the related PPD invoice. Requires the team's\n  `automatePartialPaymentComplements` default to be on and a `payment_complement`\n  automation already present on the payment. Sending more than the payment amount\n  returns `400`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Payment id.",
            "schema": {
              "type": "string"
            },
            "example": "payment_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MarkPaymentAsPaidInput"
              },
              "example": {
                "payment_form": "03",
                "date": 1767225600000,
                "ignore_emails": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment marked as paid successfully. When `amount_received` was less than the\npayment amount, the returned payment has `status: partially_paid` instead of\n`succeeded`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "payment_1234567890",
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "emails": [
                      "contabilidad@ejemplo.com"
                    ],
                    "currency": "MXN",
                    "allowed_payment_methods": [
                      "card",
                      "bank"
                    ],
                    "exchange_rate": 1,
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicios de consultoría profesional",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48",
                        "unit_name": "Unidad de servicio",
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false
                          }
                        ],
                        "team": "team_1234567890",
                        "created_at": 1767225600000,
                        "from": "api"
                      }
                    ],
                    "metadata": {},
                    "team": "team_1234567890",
                    "idempotency_key": "payment-2026-0001",
                    "from": "api",
                    "invoices": [
                      "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
                    ],
                    "livemode": true,
                    "owner": "user_1234567890",
                    "payment_form": "03",
                    "payments": [],
                    "receipts": [],
                    "refunds": [],
                    "short_url": "https://gigstack.xyz/Xk3mP9",
                    "success_url": null,
                    "status": "succeeded",
                    "total": 1160,
                    "total_refunded": 0,
                    "subtotal": 1000,
                    "taxes": 160,
                    "discount": 0,
                    "withholding_taxes": 0,
                    "created_at": 1767225600000,
                    "succeeded_at": 1767225900000,
                    "payment_processor": "api"
                  },
                  "message": "Payment marked as paid successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad Request. `error.code: validation_failed` for schema failures (including\nunknown keys), or `invalid_request_body` for\n`date cannot be in the future`, `Payment is already marked as paid`,\n`Cannot mark a cancelled payment as paid`, `amount_received cannot exceed the\npayment amount`, `Partial payment complements are not enabled for this team`,\n`Payment does not have a payment complement automation configured`, and\n`amount_received must be greater than the amount already received`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Payment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error — `Error marking payment as paid`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      }
    },
    "/payments/{id}/refund": {
      "post": {
        "operationId": "createPaymentsByIdRefund",
        "tags": [
          "Payments"
        ],
        "summary": "Refund payment",
        "description": "[Small working example](/recipes/refund)\n\n**Integration note:** Choose record-only versus an eligible Stripe refund before calling. amount is in currency units; response data.payment.amount and total_refunded are in minor units. Internal refund.status succeeded does not prove processor settlement. No idempotency key is documented for this endpoint.\n\nRefund a payment with a specified reason and amount.\n\n**gigstack Connect:** Refund other teams' payments using the `team` parameter.\n\n## Key Features\n- Partial or full refunds supported\n- Optional external processor refund handling\n- Automatic refund tracking and reporting\n- Supports Stripe integration for automatic processor refunds\n\n`reason` and `amount` are both required. `amount` must be at least **0.01** — the\nvalidator rejects anything below it.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Payment id.",
            "schema": {
              "type": "string"
            },
            "example": "payment_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefundPaymentInput"
              },
              "example": {
                "reason": "Customer requested cancellation",
                "amount": 1160,
                "external_processor_refund": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment refunded successfully",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "refund": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "example": "refund_1234567890"
                                },
                                "reason": {
                                  "type": "string",
                                  "example": "Customer requested cancellation"
                                },
                                "total": {
                                  "type": "number",
                                  "description": "The refunded amount as supplied in the request.",
                                  "example": 1160
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "succeeded"
                                  ],
                                  "example": "succeeded"
                                },
                                "timestamp": {
                                  "type": "integer",
                                  "format": "int64",
                                  "example": 1767225600000
                                },
                                "from": {
                                  "type": "string",
                                  "enum": [
                                    "api"
                                  ],
                                  "example": "api"
                                },
                                "external_processor_refund": {
                                  "type": "boolean",
                                  "example": true
                                }
                              }
                            },
                            "payment": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "example": "payment_1234567890"
                                },
                                "amount": {
                                  "type": "number",
                                  "description": "Payment amount in cents.",
                                  "example": 116000
                                },
                                "total_refunded": {
                                  "type": "number",
                                  "description": "Cumulative refunded amount in cents.",
                                  "example": 116000
                                },
                                "refund_status": {
                                  "type": "string",
                                  "example": "refunded"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "refund": {
                      "id": "re_example",
                      "reason": "Agreed partial refund",
                      "total": 116,
                      "status": "succeeded",
                      "timestamp": 1767225600000,
                      "from": "api",
                      "external_processor_refund": false
                    },
                    "payment": {
                      "id": "payment_example",
                      "amount": 116000,
                      "total_refunded": 11600,
                      "refund_status": "requires_action"
                    }
                  },
                  "message": "Refund processed successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad Request. `validation_failed` when `amount < 0.01` or the body has unknown\nkeys; `invalid_request_body` for\n`Can only refund payments that have succeeded`,\n`Total refunded amount (…) cannot exceed payment amount (…)`, and\n`External processor refund is not allowed for this payment`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Payment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error — `Error processing refund`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      }
    },
    "/payments/{id}/support-documents": {
      "post": {
        "operationId": "createPaymentsByIdSupportDocuments",
        "tags": [
          "Payments"
        ],
        "summary": "Upload support document",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nUpload a supporting document (contract, proof of delivery, etc.) for a payment.\n\n**SAT 2026 Compliance:** The Mexican tax authority (SAT) can request supporting documentation\nto validate invoices and payments. This endpoint helps maintain compliance.\n\n**gigstack Connect:** Upload documents for other teams' payments using the `team` parameter.\n\n**Supported File Types:**\n- PDF files (.pdf)\n- Images (.png, .jpg, .jpeg, .webp)\n\n**File Size Limit:** 10MB\n\n**Document Types:**\n- `contract`: Service or product contracts\n- `delivery_proof`: Proof of delivery or service completion\n- `payment_proof`: Payment receipts or confirmations\n- `communication`: Emails, messages, or agreements\n- `payment_confirmation`: Payment processor confirmations\n- `subscription_info`: Subscription or recurring service details\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Payment ID",
            "example": "payment_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UploadSupportDocumentInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document uploaded. Standardized envelope (`timestamp` in epoch ms).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/SATDocument"
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "doc_1234567890",
                    "document_type": "contract",
                    "name": "Contrato de servicios 2026",
                    "description": null,
                    "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_1234567890%2Fdocuments%2Fcontrato-2026.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                    "file_name": "contrato-2026.pdf",
                    "file_size": 284913,
                    "mime_type": "application/pdf",
                    "compliance_status": "pending_review",
                    "created_at": 1767225600000,
                    "linked_entities": [
                      {
                        "entity_type": "payment",
                        "entity_id": "payment_1234567890",
                        "linked_at": 1767225600000
                      }
                    ]
                  },
                  "message": "Support document uploaded successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Payment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      },
      "get": {
        "operationId": "getPaymentsByIdSupportDocuments",
        "tags": [
          "Payments"
        ],
        "summary": "List support documents",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nRetrieve all supporting documents attached to a payment.\n\n**gigstack Connect:** View documents for other teams' payments using the `team` parameter.\n\nDocuments are returned sorted by creation date (newest first).\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Payment ID",
            "example": "payment_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Documents retrieved, newest first. Standardized envelope (`timestamp` in epoch ms).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SATDocument"
                      }
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "doc_1234567890",
                      "document_type": "contract",
                      "name": "Contrato de servicios 2026",
                      "description": null,
                      "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_1234567890%2Fdocuments%2Fcontrato-2026.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                      "file_name": "contrato-2026.pdf",
                      "file_size": 284913,
                      "mime_type": "application/pdf",
                      "compliance_status": "pending_review",
                      "created_at": 1767225600000,
                      "linked_entities": [
                        {
                          "entity_type": "payment",
                          "entity_id": "payment_1234567890",
                          "linked_at": 1767225600000
                        }
                      ]
                    }
                  ],
                  "message": "Support documents retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Payment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/receipts": {
      "get": {
        "operationId": "listReceipts",
        "tags": [
          "Receipts"
        ],
        "summary": "List receipts",
        "description": "Retrieve a paginated list of receipts.\n\n**gigstack Connect:** View other teams' receipts using the `team` parameter.\n\n**Filters:** only `client_id`, `tax_id` and the `created[...]` range are applied. `status`, `valid_until` and\n`metadata` are accepted but **ignored** — they do not narrow the results. Filter on those fields client-side.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGtParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLtParam"
          },
          {
            "$ref": "#/components/parameters/ClientIdFilterParam"
          },
          {
            "$ref": "#/components/parameters/TaxIdFilterParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Receipts retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                },
                "example": {
                  "success": true,
                  "message": "Receipts retrieved successfully",
                  "data": [
                    {
                      "id": "receipt_1234567890",
                      "client": {
                        "id": "client_1234567890",
                        "name": "ESCUELA KEMPER URGATE",
                        "legal_name": "ESCUELA KEMPER URGATE",
                        "email": "contabilidad@ejemplo.com",
                        "bcc": [],
                        "phone": "+524421234567",
                        "tax_id": "EKU9003173C9",
                        "tax_system": "601",
                        "use": "G03",
                        "address": {
                          "street": "Av. Constituyentes",
                          "exterior": "1000",
                          "neighborhood": "Centro",
                          "city": "Querétaro",
                          "state": "QRO",
                          "zip": "76000",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "efos": {
                          "is_valid": true
                        },
                        "metadata": {},
                        "livemode": true,
                        "from": "api",
                        "owner": "user_1234567890",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      },
                      "currency": "MXN",
                      "exchange_rate": 1,
                      "from": "api",
                      "url": "https://invoicing.gigstack.pro/autofactura?id=receipt_1234567890",
                      "created_at": 1767225600000,
                      "invoices": [],
                      "items": [
                        {
                          "id": "service_1234567890",
                          "description": "Servicios de consultoría profesional",
                          "quantity": 1,
                          "unit_price": 1000,
                          "product_key": "80141503",
                          "unit_key": "E48",
                          "unit_name": "Unidad de servicio",
                          "taxes": [
                            {
                              "type": "IVA",
                              "rate": 0.16,
                              "factor": "Tasa",
                              "withholding": false
                            }
                          ],
                          "team": "team_1234567890",
                          "created_at": 1767225600000,
                          "from": "api"
                        }
                      ],
                      "livemode": true,
                      "metadata": {
                        "order_id": "ORD-12345"
                      },
                      "owner": "user_1234567890",
                      "payments": [
                        "payment_1234567890"
                      ],
                      "periodicity": "month",
                      "short_url": "https://gigstack.xyz/Rc8vQ2",
                      "status": "pending",
                      "team": "team_1234567890",
                      "valid_until": 1769817600000,
                      "automatic_invoice_error": null,
                      "payment_form": "03",
                      "total": 1160,
                      "total_refunded": 0,
                      "subtotal": 1000,
                      "taxes": 160,
                      "discount": 0,
                      "withholding_taxes": 0,
                      "idempotency_key": "receipt-key-12345"
                    }
                  ],
                  "next": null,
                  "has_more": false,
                  "total_results": 1,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createReceipts",
        "tags": [
          "Receipts"
        ],
        "summary": "Create receipt",
        "description": "[Small working example](/recipes/receipt)\n\n**Integration note:** A receipt is not yet a stamped CFDI. Repeating a creation idempotency_key returned HTTP 400 resource_conflict in staging. The tested response returned payment_form null despite a request value of 03; verify the fiscal document before issuing it.\n\nCreate a new receipt with items and client information. Receipts are pre-invoice documents\nthat can be later stamped as CFDI invoices.\n\n**Features:**\n- Automatic amount calculations with taxes\n- Flexible validity periods\n- Client auto-creation support\n- Metadata support for tracking\n- Idempotency support to prevent duplicate receipts\n\n**gigstack Connect:** Create receipts for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReceiptInput"
              },
              "example": {
                "client": {
                  "id": "client_1234567890"
                },
                "currency": "MXN",
                "items": [
                  {
                    "id": "service_1234567890",
                    "quantity": 1
                  }
                ],
                "periodicity": "month",
                "payment_form": "03",
                "idempotency_key": "receipt-key-12345",
                "metadata": {
                  "order_id": "ORD-12345"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Receipt created successfully. The receipt is stored with `status: pending` —\nno PAC call happens here, so no PAC-related error can be returned by this\noperation. Stamping happens later, via `POST /v2/receipts/{id}/stamp` or the\nself-invoicing portal.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string",
                          "example": "Receipt created successfully"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "receipt_1234567890",
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "from": "api",
                    "url": "https://invoicing.gigstack.pro/autofactura?id=receipt_1234567890",
                    "created_at": 1767225600000,
                    "invoices": [],
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicios de consultoría profesional",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48",
                        "unit_name": "Unidad de servicio",
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false
                          }
                        ],
                        "team": "team_1234567890",
                        "created_at": 1767225600000,
                        "from": "api"
                      }
                    ],
                    "livemode": true,
                    "metadata": {
                      "order_id": "ORD-12345"
                    },
                    "owner": "user_1234567890",
                    "payments": [
                      "payment_1234567890"
                    ],
                    "periodicity": "month",
                    "short_url": "https://gigstack.xyz/Rc8vQ2",
                    "status": "pending",
                    "team": "team_1234567890",
                    "valid_until": 1769817600000,
                    "automatic_invoice_error": null,
                    "payment_form": "03",
                    "total": 1160,
                    "total_refunded": 0,
                    "subtotal": 1000,
                    "taxes": 160,
                    "discount": 0,
                    "withholding_taxes": 0,
                    "idempotency_key": "receipt-key-12345"
                  },
                  "message": "Receipt created successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad Request. `error.code`:\n- `validation_failed` — schema failure, including unknown keys.\n- `invalid_request_body` — `Items are required for receipt creation`, `Exchange rate not found`.\n- `resource_conflict` — the supplied `idempotency_key` already exists. Note the\n  status is **400**, not 409, despite the code name.\n- `resource_resolution_failed` — the `client`/`items` reference could not be\n  resolved (e.g. both `id` and `search` supplied, or `safety_check` matched\n  several records).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Referenced client or service belongs to another team, or `livemode` mismatch.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Referenced client or service id was not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "A concurrent create holds the client/service lock — retry the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Team credit limit reached. Returned in the standardized envelope with\n`error.code: team_credit_limit_reached`; `error.details` carries the reason\nreported by the credit checker.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "team_credit_limit_reached",
                    "message": "Team credit limit reached",
                    "details": "Credit limit of 100 documents reached for this billing period"
                  },
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error — `An error occurred while creating receipt`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      }
    },
    "/receipts/search": {
      "get": {
        "operationId": "getReceiptsSearch",
        "tags": [
          "Receipts"
        ],
        "summary": "Search receipts",
        "description": "Full-text search across receipts using Typesense. Provides fast, typo-tolerant search capabilities.\n\n**gigstack Connect:** Access other teams' receipts using the `team` parameter.\n\n**Search Capabilities:**\n- Search across client name, email, receipt description, and metadata\n- Typo-tolerant fuzzy matching\n- Paginated results\n\n**Requirements:**\n- Typesense must be configured for your team\n- The `q` (or `query`) parameter is required\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/SearchQueryParam"
          },
          {
            "$ref": "#/components/parameters/SearchQueryBackwardCompatParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/SearchPageParam"
          },
          {
            "$ref": "#/components/parameters/FieldsParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Receipts searched successfully",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SearchResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "message": "Receipts searched successfully",
                  "data": [
                    {
                      "id": "receipt_1234567890",
                      "client": {
                        "id": "client_1234567890",
                        "name": "ESCUELA KEMPER URGATE",
                        "legal_name": "ESCUELA KEMPER URGATE",
                        "email": "contabilidad@ejemplo.com",
                        "bcc": [],
                        "phone": "+524421234567",
                        "tax_id": "EKU9003173C9",
                        "tax_system": "601",
                        "use": "G03",
                        "address": {
                          "street": "Av. Constituyentes",
                          "exterior": "1000",
                          "neighborhood": "Centro",
                          "city": "Querétaro",
                          "state": "QRO",
                          "zip": "76000",
                          "country": "MEX"
                        },
                        "is_valid": true,
                        "efos": {
                          "is_valid": true
                        },
                        "metadata": {},
                        "livemode": true,
                        "from": "api",
                        "owner": "user_1234567890",
                        "team": "team_1234567890",
                        "created_at": 1767225600000
                      },
                      "currency": "MXN",
                      "exchange_rate": 1,
                      "from": "api",
                      "url": "https://invoicing.gigstack.pro/autofactura?id=receipt_1234567890",
                      "created_at": 1767225600000,
                      "invoices": [],
                      "items": [
                        {
                          "id": "service_1234567890",
                          "description": "Servicios de consultoría profesional",
                          "quantity": 1,
                          "unit_price": 1000,
                          "product_key": "80141503",
                          "unit_key": "E48",
                          "unit_name": "Unidad de servicio",
                          "taxes": [
                            {
                              "type": "IVA",
                              "rate": 0.16,
                              "factor": "Tasa",
                              "withholding": false
                            }
                          ],
                          "team": "team_1234567890",
                          "created_at": 1767225600000,
                          "from": "api"
                        }
                      ],
                      "livemode": true,
                      "metadata": {
                        "order_id": "ORD-12345"
                      },
                      "owner": "user_1234567890",
                      "payments": [
                        "payment_1234567890"
                      ],
                      "periodicity": "month",
                      "short_url": "https://gigstack.xyz/Rc8vQ2",
                      "status": "pending",
                      "team": "team_1234567890",
                      "valid_until": 1769817600000,
                      "automatic_invoice_error": null,
                      "payment_form": "03",
                      "total": 1160,
                      "total_refunded": 0,
                      "subtotal": 1000,
                      "taxes": 160,
                      "discount": 0,
                      "withholding_taxes": 0,
                      "idempotency_key": "receipt-key-12345"
                    }
                  ],
                  "found": 1,
                  "page": 1,
                  "per_page": 10,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "missing_query": {
                    "summary": "Missing query parameter",
                    "value": {
                      "error": {
                        "code": "missing_query",
                        "message": "Query parameter is required"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "missing_typesense_key": {
                    "summary": "Typesense not configured",
                    "value": {
                      "error": {
                        "code": "missing_typesense_key",
                        "message": "Typesense API key not configured for this team"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/receipts/{id}": {
      "get": {
        "operationId": "getReceiptsById",
        "tags": [
          "Receipts"
        ],
        "summary": "Get receipt",
        "description": "Retrieve a specific receipt by ID.\n\n**gigstack Connect:** View other teams' receipts using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "receipt_1234567890",
            "description": "Receipt ID"
          },
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Receipt retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "receipt_1234567890",
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "from": "api",
                    "url": "https://invoicing.gigstack.pro/autofactura?id=receipt_1234567890",
                    "created_at": 1767225600000,
                    "invoices": [],
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicios de consultoría profesional",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48",
                        "unit_name": "Unidad de servicio",
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false
                          }
                        ],
                        "team": "team_1234567890",
                        "created_at": 1767225600000,
                        "from": "api"
                      }
                    ],
                    "livemode": true,
                    "metadata": {
                      "order_id": "ORD-12345"
                    },
                    "owner": "user_1234567890",
                    "payments": [
                      "payment_1234567890"
                    ],
                    "periodicity": "month",
                    "short_url": "https://gigstack.xyz/Rc8vQ2",
                    "status": "pending",
                    "team": "team_1234567890",
                    "valid_until": 1769817600000,
                    "automatic_invoice_error": null,
                    "payment_form": "03",
                    "total": 1160,
                    "total_refunded": 0,
                    "subtotal": 1000,
                    "taxes": 160,
                    "discount": 0,
                    "withholding_taxes": 0,
                    "idempotency_key": "receipt-key-12345"
                  },
                  "message": "Receipt retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Receipt not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteReceiptsById",
        "tags": [
          "Receipts"
        ],
        "summary": "Cancel receipt",
        "description": "Cancel a receipt. This action cannot be undone.\n\n**gigstack Connect:** Cancel other teams' receipts using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "receipt_1234567890",
            "description": "Receipt ID"
          },
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Receipt canceled successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "receipt_1234567890",
                    "status": "completed",
                    "cancelled_at": 1767225600000
                  },
                  "message": "Receipt cancelled successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/receipts/{id}/stamp": {
      "post": {
        "operationId": "createReceiptsByIdStamp",
        "tags": [
          "Receipts"
        ],
        "summary": "Stamp receipt",
        "description": "Convert a receipt into a CFDI invoice by stamping it with SAT.\n\nOnly receipts with `status: pending` can be stamped. A receipt that already has\nentries in `invoices[]` is returned as-is with a `200` and no new CFDI; any other\nnon-pending receipt (a cancelled one is stored as `completed`) is rejected with a\n`409`.\n\n**Stamp Options:**\n- `client`: Stamp to the associated client\n- `general_public_national`: Stamp to Mexican general public\n- `general_public_foreign`: Stamp to foreign general public\n\n**gigstack Connect:** Stamp other teams' receipts using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "receipt_1234567890",
            "description": "Receipt ID"
          },
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "stamp_to"
                ],
                "properties": {
                  "idempotency_key": {
                    "type": "string",
                    "nullable": true,
                    "example": "stamp-receipt-2026-09-11-001",
                    "description": "Optional. A retry that reuses the key returns 409 with the receipt id instead of attempting a second stamp."
                  },
                  "stamp_to": {
                    "type": "string",
                    "enum": [
                      "client",
                      "general_public_national",
                      "general_public_foreign"
                    ],
                    "example": "client",
                    "description": "Who to stamp the receipt to"
                  },
                  "fiscal_information": {
                    "type": "object",
                    "nullable": true,
                    "properties": {
                      "legal_name": {
                        "type": "string",
                        "nullable": true,
                        "example": "Juan Pérez García"
                      },
                      "tax_id": {
                        "type": "string",
                        "nullable": true,
                        "example": "PEGJ800101ABC"
                      },
                      "tax_system": {
                        "type": "string",
                        "nullable": true,
                        "example": "601"
                      },
                      "zip": {
                        "type": "string",
                        "nullable": true,
                        "example": "01000"
                      }
                    },
                    "description": "Custom fiscal information (overrides client data)"
                  },
                  "date": {
                    "type": "number",
                    "nullable": true,
                    "example": 1677651234000,
                    "description": "Custom invoice date (timestamp in milliseconds)"
                  }
                }
              },
              "example": {
                "stamp_to": "client",
                "date": 1767225600000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Receipt stamped successfully. **This handler predates the standardized\nenvelope** — it returns the raw shape `{ \"message\": …, \"data\": … }` with no\n`success` or `timestamp` keys.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Receipt stamped successfully"
                    },
                    "data": {
                      "type": "object",
                      "description": "The stamped receipt."
                    }
                  }
                },
                "example": {
                  "message": "Receipt stamped successfully",
                  "data": {
                    "id": "receipt_1234567890",
                    "client": {
                      "id": "client_1234567890",
                      "name": "ESCUELA KEMPER URGATE",
                      "legal_name": "ESCUELA KEMPER URGATE",
                      "email": "contabilidad@ejemplo.com",
                      "bcc": [],
                      "phone": "+524421234567",
                      "tax_id": "EKU9003173C9",
                      "tax_system": "601",
                      "use": "G03",
                      "address": {
                        "street": "Av. Constituyentes",
                        "exterior": "1000",
                        "neighborhood": "Centro",
                        "city": "Querétaro",
                        "state": "QRO",
                        "zip": "76000",
                        "country": "MEX"
                      },
                      "is_valid": true,
                      "efos": {
                        "is_valid": true
                      },
                      "metadata": {},
                      "livemode": true,
                      "from": "api",
                      "owner": "user_1234567890",
                      "team": "team_1234567890",
                      "created_at": 1767225600000
                    },
                    "currency": "MXN",
                    "exchange_rate": 1,
                    "from": "api",
                    "url": "https://invoicing.gigstack.pro/autofactura?id=receipt_1234567890",
                    "created_at": 1767225600000,
                    "invoices": [
                      "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
                    ],
                    "items": [
                      {
                        "id": "service_1234567890",
                        "description": "Servicios de consultoría profesional",
                        "quantity": 1,
                        "unit_price": 1000,
                        "product_key": "80141503",
                        "unit_key": "E48",
                        "unit_name": "Unidad de servicio",
                        "taxes": [
                          {
                            "type": "IVA",
                            "rate": 0.16,
                            "factor": "Tasa",
                            "withholding": false
                          }
                        ],
                        "team": "team_1234567890",
                        "created_at": 1767225600000,
                        "from": "api"
                      }
                    ],
                    "livemode": true,
                    "metadata": {
                      "order_id": "ORD-12345"
                    },
                    "owner": "user_1234567890",
                    "payments": [
                      "payment_1234567890"
                    ],
                    "periodicity": "month",
                    "short_url": "https://gigstack.xyz/Rc8vQ2",
                    "status": "completed",
                    "team": "team_1234567890",
                    "valid_until": 1769817600000,
                    "automatic_invoice_error": null,
                    "payment_form": "03",
                    "total": 1160,
                    "total_refunded": 0,
                    "subtotal": 1000,
                    "taxes": 160,
                    "discount": 0,
                    "withholding_taxes": 0,
                    "idempotency_key": "receipt-key-12345"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request, returned in the raw legacy shape. Cases:\n- body validation failure — `{ \"error\": \"Invalid request body\", \"errors\": [...] }`\n- `fiscal_information cannot be provided when stamp_to is general_public`\n- `fiscal_information is required when stamp_to is client and receipt has no client`\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "`Receipt data not found`, or `Client not found in database` when `stamp_to: client`\nresolves to a client document that no longer exists.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "The receipt is not pending, so it cannot be stamped. Receipts that already\nproduced a CFDI return `200` with their `invoices[]` instead.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal error, raw shape. **PAC failures surface here as 500, not 503** — when\nthe stamping provider returns a non-OK response the handler emits\n`{ \"error\": <provider message>, \"message\": \"Failed to process receipt: <status> <statusText>\" }`.\nAlso covers `Receipt reference not found` and the uncaught-exception body\n`{ \"error\": { \"code\": \"stamp_receipt_handler_error\", \"message\": …, \"details\": … }, \"message\": … }`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/receipts/{id}/reopen": {
      "post": {
        "operationId": "createReceiptsByIdReopen",
        "tags": [
          "Receipts"
        ],
        "summary": "Reopen receipt",
        "description": "Return a receipt whose self-invoicing failed to `status: pending`, so the client can\ntry again from the self-invoicing portal.\n\nOnly a receipt that is **not** `pending` and has **no** entries in `invoices[]` can be\nreopened: an already-pending receipt and one that produced a CFDI are both rejected\nwith `409`. The response clears `automatic_invoice_error`; who reopened it and why are\nrecorded on the receipt but are not part of the API response.\n\n**gigstack Connect:** reopen other teams' receipts with the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "receipt_1234567890",
            "description": "Receipt ID"
          },
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 500,
                    "example": "El cliente pidió corregir su RFC",
                    "description": "Optional note kept on the receipt for your own audit trail."
                  }
                }
              },
              "example": {
                "reason": "El cliente pidió corregir su RFC"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Receipt reopened for self-invoicing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "receipt_1234567890",
                    "status": "pending",
                    "automatic_invoice_error": null,
                    "periodicity": "month",
                    "valid_until": 1769817600000
                  },
                  "message": "Receipt reopened for self-invoicing",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "`reason` is not a string, or is longer than 500 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The receipt belongs to another team.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The receipt does not exist, or its `livemode` does not match the API key — a\ntest key never resolves a live receipt, and a live key never resolves a test\none, so the other environment's ids are answered as not found.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "The receipt is already `pending`, or it already has one or more invoices.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/retentions": {
      "get": {
        "operationId": "listRetentions",
        "tags": [
          "Retentions"
        ],
        "summary": "List retentions",
        "description": "Retrieve a paginated list of tax retention documents (CFDI Retenciones 2.0).\n\n**gigstack Connect:** View other teams' retentions using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGtParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLtParam"
          },
          {
            "$ref": "#/components/parameters/ClientIdFilterParam"
          },
          {
            "$ref": "#/components/parameters/TaxIdFilterParam"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "valid",
                "canceled"
              ]
            },
            "description": "Filter by retention status"
          },
          {
            "name": "retention_key",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by SAT retention key (cveRetenc), e.g. \"26\" for Plataformas Tecnológicas"
          }
        ],
        "responses": {
          "200": {
            "description": "Retentions retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                },
                "examples": {
                  "list_retentions": {
                    "summary": "List of retentions",
                    "value": {
                      "data": [
                        {
                          "id": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                          "uuid": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                          "status": "valid",
                          "document_type": "retenciones",
                          "retention_key": "26",
                          "folio_number": "1",
                          "series": "RET",
                          "issuer": {
                            "legal_name": "MI EMPRESA SA DE CV",
                            "tax_id": "MEE200101ABC",
                            "tax_system": "601"
                          },
                          "receiver": {
                            "legal_name": "GRUPO JINIM",
                            "tax_id": "EKU9003173C9",
                            "nationality": "Nacional"
                          },
                          "period": {
                            "start": 1,
                            "end": 1,
                            "year": 2026
                          },
                          "totals": {
                            "total_operation": 93116.98,
                            "total_taxable": 93116.98,
                            "total_exempt": 0,
                            "total_retained": 9777.27,
                            "tax_retained": [
                              {
                                "tax": "001",
                                "base": 93116.98,
                                "amount": 2327.92,
                                "payment_type": "03"
                              },
                              {
                                "tax": "002",
                                "base": 14898.71,
                                "amount": 7449.35,
                                "payment_type": "01"
                              }
                            ]
                          },
                          "stamp": {
                            "uuid": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                            "stamped_at": "2026-01-15T10:30:45.000Z"
                          },
                          "livemode": true,
                          "created_at": 1736942445000
                        },
                        {
                          "id": "c4e2f1a8-9b3d-4e7f-a1c2-8d5e6f7a0b3c",
                          "uuid": "c4e2f1a8-9b3d-4e7f-a1c2-8d5e6f7a0b3c",
                          "status": "valid",
                          "document_type": "retenciones",
                          "retention_key": "01",
                          "folio_number": "2",
                          "series": "RET",
                          "receiver": {
                            "legal_name": "JUAN PEREZ GARCIA",
                            "tax_id": "PEGJ800101ABC",
                            "nationality": "Nacional"
                          },
                          "period": {
                            "start": 1,
                            "end": 3,
                            "year": 2026
                          },
                          "totals": {
                            "total_operation": 50000,
                            "total_taxable": 50000,
                            "total_exempt": 0,
                            "total_retained": 5000,
                            "tax_retained": [
                              {
                                "tax": "001",
                                "base": 50000,
                                "amount": 5000,
                                "payment_type": "03"
                              }
                            ]
                          },
                          "livemode": true,
                          "created_at": 1736510430000
                        }
                      ],
                      "has_more": false,
                      "message": "Operation completed successfully",
                      "total_results": 1,
                      "success": true,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          }
        }
      },
      "post": {
        "operationId": "createRetentions",
        "tags": [
          "Retentions"
        ],
        "summary": "Create retention",
        "description": "Create and stamp a new tax retention document (CFDI Retenciones 2.0).\n\nThe API accepts a **simplified format** — the backend handles:\n- **Client lookup** by ID (fetches RFC, legal name, address automatically)\n- **Nationality detection** from client's country\n- **Tax code mapping** (`ISR` → 001, `IVA` → 002, `IEPS` → 003)\n- **Payment type defaults** per tax (ISR → provisional, IVA/IEPS → definitivo)\n- **Totals auto-calculation** (taxable = operation − exempt, retained = sum of taxes)\n- **Folio auto-generation**\n- SAT stamping, PDF and XML generation\n\n**gigstack Connect:** Create retentions for other teams using the `team` parameter.\n\n## Conditional requirements per `retention_key`\n\n`retention_key` is validated as a free-form string — any SAT key is accepted — but three\nkeys carry extra requirements enforced before the document is stamped. A violation\nreturns `400` with `error.code: invalid_request_body` and the message quoted below.\n\n| `retention_key` | additional requirement | error message on violation |\n|---|---|---|\n| `16` — Intereses | `interest` object is required | `interest object is required for retention key 16 (Intereses)` |\n| `25` — Otro tipo de retenciones | `retention_description` is required and non-empty | `retention_description is required for retention key 25 (Otro tipo de retenciones)` |\n| `26` — Plataformas Tecnológicas | `platform_services` object is required **and** `taxes` must contain at least one entry whose `tax` is not `IVA` (i.e. `ISR` or `IEPS`) | `platform_services object is required for retention key 26 (Plataformas Tecnológicas)` / `At least one non-IVA tax (ISR or IEPS) is required for Plataformas Tecnológicas` |\n\nEvery other key requires only the base fields (`retention_key`, `client`,\n`period_start`, `period_end`, `period_year`, `total_operation`, `taxes`).\n\nWithin `interest`, `financial_system`, `nominal_interest` and `real_interest` are\nrequired. Within `platform_services`, `periodicity` and `services` are required, and\neach entry in `services` requires `payment_form`, `service_type`, `service_date` and\n`price_without_tax`.\n\n> Unlike the other modules, this endpoint **strips** unknown keys instead of rejecting\n> them (`stripUnknown: true`), so an undeclared field is silently discarded rather than\n> returning `400`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "retention_key",
                  "client",
                  "period_start",
                  "period_end",
                  "period_year",
                  "total_operation",
                  "taxes"
                ],
                "properties": {
                  "retention_key": {
                    "type": "string",
                    "description": "SAT retention type code (01-26). E.g. \"26\" for Plataformas Tecnológicas",
                    "example": "26"
                  },
                  "client": {
                    "type": "object",
                    "description": "Client reference. Same format as invoices/payments. Three modes:\n- **By ID:** `{ id: \"client_123\" }` — looks up existing client\n- **By search:** `{ search: { on_key: \"tax_id\", on_value: \"XAXX010101000\", auto_create: true } }` — finds or creates\n- **Inline:** `{ tax_id: \"XAXX010101000\", legal_name: \"EMPRESA SA\", address: { zip: \"06700\" } }` — creates on-the-fly\n",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Existing client ID"
                      },
                      "search": {
                        "type": "object",
                        "description": "Search for client by field value",
                        "properties": {
                          "on_key": {
                            "type": "string",
                            "description": "Field to search on (e.g. \"tax_id\", \"email\", \"rfc\")"
                          },
                          "on_value": {
                            "type": "string",
                            "description": "Value to match"
                          },
                          "auto_create": {
                            "type": "boolean",
                            "description": "Create client if not found (default false)"
                          },
                          "safety_check": {
                            "type": "boolean",
                            "description": "Fail if multiple clients match (default false)"
                          }
                        }
                      },
                      "tax_id": {
                        "type": "string",
                        "description": "RFC / Tax ID (for inline creation)"
                      },
                      "legal_name": {
                        "type": "string",
                        "description": "Legal name (for inline creation)"
                      },
                      "email": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "address": {
                        "type": "object",
                        "properties": {
                          "zip": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string"
                          },
                          "street": {
                            "type": "string"
                          },
                          "state": {
                            "type": "string"
                          }
                        }
                      },
                      "tax_system": {
                        "type": "string",
                        "description": "Tax system code (e.g. \"601\")"
                      }
                    }
                  },
                  "period_start": {
                    "type": "number",
                    "description": "Start month (1-12)",
                    "example": 1
                  },
                  "period_end": {
                    "type": "number",
                    "description": "End month (1-12)",
                    "example": 3
                  },
                  "period_year": {
                    "type": "number",
                    "description": "Fiscal year",
                    "example": 2026
                  },
                  "total_operation": {
                    "type": "number",
                    "description": "Total operation amount. Taxable amount is auto-calculated as `total_operation - total_exempt`",
                    "example": 93116.98
                  },
                  "total_exempt": {
                    "type": "number",
                    "nullable": true,
                    "description": "Total exempt amount (defaults to 0)",
                    "example": 0
                  },
                  "taxes": {
                    "type": "array",
                    "description": "Retained taxes. Use friendly names (ISR, IVA, IEPS) — SAT codes are mapped automatically",
                    "items": {
                      "type": "object",
                      "required": [
                        "tax",
                        "base",
                        "amount"
                      ],
                      "properties": {
                        "tax": {
                          "type": "string",
                          "description": "Tax name: ISR, IVA, or IEPS (mapped to SAT codes 001, 002, 003)",
                          "example": "ISR"
                        },
                        "base": {
                          "type": "number",
                          "description": "Tax base amount",
                          "example": 93116.98
                        },
                        "amount": {
                          "type": "number",
                          "description": "Retained amount",
                          "example": 2327.92
                        },
                        "payment_type": {
                          "type": "string",
                          "nullable": true,
                          "description": "Override payment type (01=Definitivo, 03=Provisional). Defaults: ISR→03, IVA→01, IEPS→01"
                        }
                      }
                    }
                  },
                  "series": {
                    "type": "string",
                    "nullable": true,
                    "description": "Series for folio management (defaults to \"RET\")"
                  },
                  "metadata": {
                    "type": "object",
                    "nullable": true,
                    "description": "Custom metadata"
                  },
                  "idempotency_key": {
                    "type": "string",
                    "nullable": true,
                    "description": "Optional stored reference. This handler does not claim or replay this key to prevent duplicate issuance. Reconcile an ambiguous result before another request; do not assume retry safety."
                  },
                  "retention_description": {
                    "type": "string",
                    "nullable": true,
                    "description": "Required only for key \"25\" (Otro tipo de retenciones). Free-text description of the retention type."
                  },
                  "interest": {
                    "type": "object",
                    "nullable": true,
                    "description": "Required only for key \"16\" (Intereses). Financial interest complement data.",
                    "properties": {
                      "financial_system": {
                        "type": "string",
                        "description": "Financial system flag (SI/NO)",
                        "enum": [
                          "SI",
                          "NO"
                        ]
                      },
                      "withdrawal_aores": {
                        "type": "string",
                        "nullable": true,
                        "description": "Retiro AORES flag (SI/NO)",
                        "enum": [
                          "SI",
                          "NO",
                          null
                        ]
                      },
                      "financial_derivatives": {
                        "type": "string",
                        "nullable": true,
                        "description": "Financial derivatives flag (SI/NO)",
                        "enum": [
                          "SI",
                          "NO",
                          null
                        ]
                      },
                      "nominal_interest": {
                        "type": "number",
                        "description": "Nominal interest amount (3 decimal places)"
                      },
                      "real_interest": {
                        "type": "number",
                        "description": "Real interest amount (3 decimal places)"
                      },
                      "loss": {
                        "type": "number",
                        "nullable": true,
                        "description": "Loss amount (3 decimal places)"
                      }
                    }
                  },
                  "platform_services": {
                    "type": "object",
                    "nullable": true,
                    "description": "Required only for key \"26\" (Plataformas Tecnológicas). Service details for technology platform retentions. Header totals (IVA trasladado, ISR retenido, etc.) are auto-calculated.",
                    "required": [
                      "periodicity",
                      "services"
                    ],
                    "properties": {
                      "periodicity": {
                        "type": "string",
                        "description": "Reporting periodicity: 01=Diario, 02=Semanal, 03=Quincenal, 04=Mensual, 05=Bimestral",
                        "example": "04"
                      },
                      "services": {
                        "type": "array",
                        "description": "Individual service entries",
                        "items": {
                          "type": "object",
                          "required": [
                            "payment_form",
                            "service_type",
                            "service_date",
                            "price_without_tax"
                          ],
                          "properties": {
                            "payment_form": {
                              "type": "string",
                              "description": "Payment form: 01=Efectivo, 02=Transferencia, 03=Tarjeta débito, 04=Tarjeta crédito, 05=Monedero electrónico",
                              "example": "02"
                            },
                            "service_type": {
                              "type": "string",
                              "description": "Service type: 01=Transporte terrestre, 02=Entrega alimentos, 03=Hospedaje, 04=Otros",
                              "example": "01"
                            },
                            "service_date": {
                              "type": "string",
                              "description": "Service date (YYYY-MM-DD)",
                              "example": "2026-01-15"
                            },
                            "price_without_tax": {
                              "type": "number",
                              "description": "Service price without IVA",
                              "example": 500
                            },
                            "tax_rate": {
                              "type": "number",
                              "nullable": true,
                              "description": "IVA tax rate (defaults to 0.16 = 16%)",
                              "example": 0.16
                            },
                            "commission": {
                              "type": "number",
                              "nullable": true,
                              "description": "Platform commission amount",
                              "example": 125
                            },
                            "government_contribution": {
                              "type": "number",
                              "nullable": true,
                              "description": "Government contribution amount (if applicable)"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "examples": {
                "plataformas_tecnologicas": {
                  "summary": "Plataformas Tecnológicas (key 26) — with services complement",
                  "description": "Digital platform retention (Uber, Rappi, etc.). Requires platform_services with service details. Header totals are auto-calculated from services and taxes.",
                  "value": {
                    "retention_key": "26",
                    "client": {
                      "id": "abc123clientId"
                    },
                    "period_start": 1,
                    "period_end": 1,
                    "period_year": 2026,
                    "total_operation": 93116.98,
                    "total_exempt": 0,
                    "taxes": [
                      {
                        "tax": "ISR",
                        "base": 93116.98,
                        "amount": 2327.92
                      },
                      {
                        "tax": "IVA",
                        "base": 14898.71,
                        "amount": 7449.35
                      }
                    ],
                    "platform_services": {
                      "periodicity": "04",
                      "services": [
                        {
                          "payment_form": "02",
                          "service_type": "01",
                          "service_date": "2026-01-10",
                          "price_without_tax": 46558.49,
                          "tax_rate": 0.16,
                          "commission": 11639.62
                        },
                        {
                          "payment_form": "02",
                          "service_type": "01",
                          "service_date": "2026-01-20",
                          "price_without_tax": 46558.49,
                          "tax_rate": 0.16,
                          "commission": 11639.62
                        }
                      ]
                    }
                  }
                },
                "intereses": {
                  "summary": "Intereses (key 16) — with interest complement",
                  "description": "Interest income retention. Requires the interest object with financial system details.",
                  "value": {
                    "retention_key": "16",
                    "client": {
                      "search": {
                        "on_key": "tax_id",
                        "on_value": "BNK200101ABC",
                        "auto_create": false
                      }
                    },
                    "period_start": 1,
                    "period_end": 12,
                    "period_year": 2026,
                    "total_operation": 150000,
                    "total_exempt": 0,
                    "taxes": [
                      {
                        "tax": "ISR",
                        "base": 150000,
                        "amount": 3000
                      }
                    ],
                    "interest": {
                      "financial_system": "SI",
                      "withdrawal_aores": "NO",
                      "financial_derivatives": "NO",
                      "nominal_interest": 8500.5,
                      "real_interest": 5200.3,
                      "loss": 0
                    }
                  }
                },
                "honorarios_profesionales": {
                  "summary": "Honorarios profesionales (key 01) — ISR only",
                  "description": "Professional fees retention. Only ISR is withheld (typically 10% of the gross amount).",
                  "value": {
                    "retention_key": "01",
                    "client": {
                      "id": "client_professional_abc"
                    },
                    "period_start": 1,
                    "period_end": 3,
                    "period_year": 2026,
                    "total_operation": 50000,
                    "total_exempt": 0,
                    "taxes": [
                      {
                        "tax": "ISR",
                        "base": 50000,
                        "amount": 5000
                      }
                    ]
                  }
                },
                "arrendamiento": {
                  "summary": "Arrendamiento (key 02) — ISR + IVA",
                  "description": "Rental income retention. ISR (10%) and IVA (2/3 of IVA) are withheld.",
                  "value": {
                    "retention_key": "02",
                    "client": {
                      "id": "client_landlord_xyz"
                    },
                    "period_start": 1,
                    "period_end": 1,
                    "period_year": 2026,
                    "total_operation": 30000,
                    "total_exempt": 0,
                    "taxes": [
                      {
                        "tax": "ISR",
                        "base": 30000,
                        "amount": 3000
                      },
                      {
                        "tax": "IVA",
                        "base": 4800,
                        "amount": 3200
                      }
                    ]
                  }
                },
                "with_exempt_and_metadata": {
                  "summary": "With exempt amount, series, and metadata",
                  "description": "Full example with all optional fields. Taxable amount is auto-calculated as total_operation minus total_exempt.",
                  "value": {
                    "retention_key": "14",
                    "client": {
                      "tax_id": "EMP200101ABC",
                      "legal_name": "EMPRESA EJEMPLO SA DE CV",
                      "address": {
                        "zip": "06700",
                        "country": "MEX"
                      }
                    },
                    "period_start": 1,
                    "period_end": 6,
                    "period_year": 2026,
                    "total_operation": 100000,
                    "total_exempt": 20000,
                    "taxes": [
                      {
                        "tax": "ISR",
                        "base": 80000,
                        "amount": 8000
                      },
                      {
                        "tax": "IVA",
                        "base": 12800,
                        "amount": 8533.33
                      }
                    ],
                    "series": "RET-A",
                    "metadata": {
                      "internal_ref": "Q1-2026-RETENTION",
                      "department": "finance"
                    },
                    "idempotency_key": "ret-2026-q1-client456"
                  }
                },
                "otro_tipo_retenciones": {
                  "summary": "Otro tipo de retenciones (key 25) — with description",
                  "description": "Generic retention type. Requires retention_description to describe the type of retention.",
                  "value": {
                    "retention_key": "25",
                    "client": {
                      "id": "client_misc_abc"
                    },
                    "period_start": 1,
                    "period_end": 6,
                    "period_year": 2026,
                    "total_operation": 40000,
                    "total_exempt": 0,
                    "taxes": [
                      {
                        "tax": "ISR",
                        "base": 40000,
                        "amount": 4000
                      }
                    ],
                    "retention_description": "Retención por servicios de consultoría especializada en seguridad informática"
                  }
                },
                "isr_only_with_custom_payment_type": {
                  "summary": "ISR with custom payment type override",
                  "description": "Override the default payment type. By default ISR uses \"03\" (provisional), but you can set it to \"01\" (definitivo) if needed.",
                  "value": {
                    "retention_key": "01",
                    "client": {
                      "id": "client_consultant_789"
                    },
                    "period_start": 3,
                    "period_end": 3,
                    "period_year": 2026,
                    "total_operation": 25000,
                    "taxes": [
                      {
                        "tax": "ISR",
                        "base": 25000,
                        "amount": 2500,
                        "payment_type": "01"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Retention created and stamped successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "examples": {
                  "success": {
                    "summary": "Retention stamped successfully",
                    "value": {
                      "message": "Retention created successfully",
                      "data": {
                        "id": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                        "uuid": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                        "status": "valid",
                        "document_type": "retenciones",
                        "retention_key": "26",
                        "folio_number": "1",
                        "series": "RET",
                        "issuer": {
                          "legal_name": "MI EMPRESA SA DE CV",
                          "tax_id": "MEE200101ABC",
                          "tax_system": "601"
                        },
                        "receiver": {
                          "legal_name": "GRUPO JINIM",
                          "tax_id": "EKU9003173C9",
                          "nationality": "Nacional"
                        },
                        "period": {
                          "start": 1,
                          "end": 1,
                          "year": 2026
                        },
                        "totals": {
                          "total_operation": 93116.98,
                          "total_taxable": 93116.98,
                          "total_exempt": 0,
                          "total_retained": 9777.27,
                          "tax_retained": [
                            {
                              "tax": "001",
                              "base": 93116.98,
                              "amount": 2327.92,
                              "payment_type": "03"
                            },
                            {
                              "tax": "002",
                              "base": 14898.71,
                              "amount": 7449.35,
                              "payment_type": "01"
                            }
                          ]
                        },
                        "stamp": {
                          "uuid": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                          "stamped_at": "2026-01-15T10:30:45.000Z"
                        },
                        "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=9d9b0e5b-034c-42f7-bd21-3a868a57c13e&re=MEE200101ABC&rr=EKU9003173C9&tt=93116.98&fe=abcd1234",
                        "livemode": true,
                        "created_at": 1736942445000,
                        "metadata": null
                      },
                      "success": true,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request or stamping error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "validation_error": {
                    "summary": "Missing required fields",
                    "value": {
                      "error": {
                        "code": "bad_request",
                        "message": "retention_key: Missing required field; taxes: Missing required field"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "client_not_found": {
                    "summary": "Client ID not found",
                    "value": {
                      "error": {
                        "code": "bad_request",
                        "message": "Client not found: invalid_client_id"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "no_provider": {
                    "summary": "No SAT provider configured",
                    "value": {
                      "error": {
                        "code": "bad_request",
                        "message": "No SAT provider configured for this team"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "stamping_error": {
                    "summary": "SAT stamping failed",
                    "value": {
                      "error": {
                        "code": "cfdi_service_error",
                        "message": "CFDI33184 - El valor del atributo RFC del receptor no existe en la lista de RFC inscritos no cancelados del SAT"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          }
        }
      }
    },
    "/retentions/{id}": {
      "get": {
        "operationId": "getRetentionsById",
        "tags": [
          "Retentions"
        ],
        "summary": "Get retention",
        "description": "Retrieve a specific tax retention document by ID (UUID).\n\n**gigstack Connect:** View other teams' retentions using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Retention UUID",
            "example": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e"
          },
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Retention retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "examples": {
                  "valid_retention": {
                    "summary": "Valid stamped retention",
                    "value": {
                      "message": "Retention retrieved successfully",
                      "data": {
                        "id": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                        "uuid": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                        "status": "valid",
                        "document_type": "retenciones",
                        "retention_key": "26",
                        "folio_number": "1",
                        "series": "RET",
                        "issuer": {
                          "legal_name": "MI EMPRESA SA DE CV",
                          "tax_id": "MEE200101ABC",
                          "tax_system": "601"
                        },
                        "receiver": {
                          "legal_name": "GRUPO JINIM",
                          "tax_id": "EKU9003173C9",
                          "nationality": "Nacional"
                        },
                        "period": {
                          "start": 1,
                          "end": 1,
                          "year": 2026
                        },
                        "totals": {
                          "total_operation": 93116.98,
                          "total_taxable": 93116.98,
                          "total_exempt": 0,
                          "total_retained": 9777.27,
                          "tax_retained": [
                            {
                              "tax": "001",
                              "base": 93116.98,
                              "amount": 2327.92,
                              "payment_type": "03"
                            },
                            {
                              "tax": "002",
                              "base": 14898.71,
                              "amount": 7449.35,
                              "payment_type": "01"
                            }
                          ]
                        },
                        "stamp": {
                          "uuid": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                          "stamped_at": "2026-01-15T10:30:45.000Z"
                        },
                        "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=9d9b0e5b-034c-42f7-bd21-3a868a57c13e&re=MEE200101ABC&rr=EKU9003173C9&tt=93116.98&fe=abcd1234",
                        "livemode": true,
                        "created_at": 1736942445000,
                        "metadata": null
                      },
                      "success": true,
                      "timestamp": 1767225600000
                    }
                  },
                  "canceled_retention": {
                    "summary": "Canceled retention",
                    "value": {
                      "message": "Retention retrieved successfully",
                      "data": {
                        "id": "c4e2f1a8-9b3d-4e7f-a1c2-8d5e6f7a0b3c",
                        "uuid": "c4e2f1a8-9b3d-4e7f-a1c2-8d5e6f7a0b3c",
                        "status": "canceled",
                        "document_type": "retenciones",
                        "retention_key": "01",
                        "folio_number": "5",
                        "series": "RET",
                        "issuer": {
                          "legal_name": "MI EMPRESA SA DE CV",
                          "tax_id": "MEE200101ABC",
                          "tax_system": "601"
                        },
                        "receiver": {
                          "legal_name": "JUAN PEREZ GARCIA",
                          "tax_id": "PEGJ800101ABC",
                          "nationality": "Nacional"
                        },
                        "period": {
                          "start": 1,
                          "end": 3,
                          "year": 2026
                        },
                        "totals": {
                          "total_operation": 50000,
                          "total_taxable": 50000,
                          "total_exempt": 0,
                          "total_retained": 5000,
                          "tax_retained": [
                            {
                              "tax": "001",
                              "base": 50000,
                              "amount": 5000,
                              "payment_type": "03"
                            }
                          ]
                        },
                        "stamp": {
                          "uuid": "c4e2f1a8-9b3d-4e7f-a1c2-8d5e6f7a0b3c",
                          "stamped_at": "2026-01-10T14:20:30.000Z"
                        },
                        "verification_url": "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx?id=c4e2f1a8-9b3d-4e7f-a1c2-8d5e6f7a0b3c&re=MEE200101ABC&rr=PEGJ800101ABC&tt=50000.00&fe=efgh5678",
                        "livemode": true,
                        "created_at": 1736510430000,
                        "metadata": null
                      },
                      "success": true,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Retention not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteRetentionsById",
        "tags": [
          "Retentions"
        ],
        "summary": "Cancel retention",
        "description": "Cancel a stamped tax retention document with the SAT.\n\n**Cancellation motives** (SAT catalog):\n- `01` - Comprobante emitido con errores con relación\n- `02` - Comprobante emitido con errores sin relación\n- `03` - No se llevó a cabo la operación\n- `04` - Operación nominativa relacionada en una factura global\n\n**gigstack Connect:** Cancel other teams' retentions using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Retention UUID",
            "example": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e"
          },
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "motive"
                ],
                "properties": {
                  "motive": {
                    "type": "string",
                    "description": "SAT cancellation motive code",
                    "enum": [
                      "01",
                      "02",
                      "03",
                      "04"
                    ],
                    "example": "02"
                  },
                  "replace_uuid": {
                    "type": "string",
                    "description": "UUID of replacement document (required when motive is \"01\")"
                  }
                }
              },
              "examples": {
                "cancel_with_errors": {
                  "summary": "Cancel — document had errors (no replacement)",
                  "value": {
                    "motive": "02"
                  }
                },
                "cancel_with_replacement": {
                  "summary": "Cancel — replace with new document",
                  "description": "Motive 01 requires the UUID of the replacement document",
                  "value": {
                    "motive": "01",
                    "replace_uuid": "a1b2c3d4-5678-90ab-cdef-1234567890ab"
                  }
                },
                "cancel_not_carried_out": {
                  "summary": "Cancel — operation not carried out",
                  "value": {
                    "motive": "03"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Retention canceled successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "examples": {
                  "canceled": {
                    "summary": "Retention canceled",
                    "value": {
                      "message": "Retention canceled successfully",
                      "data": {
                        "id": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                        "uuid": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e",
                        "status": "canceled",
                        "document_type": "retenciones",
                        "retention_key": "26",
                        "cancellation": {
                          "motive": "02",
                          "canceled_at": "2026-03-06T12:00:00.000Z"
                        }
                      },
                      "success": true,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request or cancellation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "already_canceled": {
                    "summary": "Already canceled",
                    "value": {
                      "error": {
                        "code": "bad_request",
                        "message": "Retention is already canceled"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "missing_replacement": {
                    "summary": "Missing replacement UUID for motive 01",
                    "value": {
                      "error": {
                        "code": "bad_request",
                        "message": "replace_uuid is required when motive is 01"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "`Retention not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "resource_not_found",
                    "message": "Retention not found"
                  },
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/retentions/{id}/files": {
      "get": {
        "operationId": "getRetentionsByIdFiles",
        "tags": [
          "Retentions"
        ],
        "summary": "Get retention files",
        "description": "Retrieve PDF and/or XML files for a stamped tax retention document.\n\nUse `file_type` query parameter to request specific file types.\n\n**gigstack Connect:** Access other teams' retention files using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Retention UUID",
            "example": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e"
          },
          {
            "name": "file_type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pdf",
                "xml"
              ]
            },
            "description": "Filter by file type. If omitted, returns both PDF and XML."
          },
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Files retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "content": {
                            "type": "string",
                            "description": "Base64-encoded file content"
                          },
                          "filename": {
                            "type": "string",
                            "example": "9d9b0e5b-034c-42f7-bd21-3a868a57c13e.pdf"
                          },
                          "type": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string",
                      "example": "Files retrieved successfully"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "content": "JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PC9UeXBlIC9DYXRhbG9nPj4K...",
                      "filename": "7F3A1C2E-4B5D-4E6F-8A9B-0C1D2E3F4A5B.pdf",
                      "type": "application/pdf"
                    }
                  ],
                  "message": "Files retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Files not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        }
      }
    },
    "/teams": {
      "get": {
        "operationId": "listTeams",
        "tags": [
          "Teams"
        ],
        "summary": "List teams",
        "description": "Retrieve a paginated list of teams.\n\n**gigstack Connect:** Access other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGtParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLtParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Teams retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiPublicTeam"
                      }
                    },
                    "next": {
                      "type": "string",
                      "nullable": true,
                      "description": "Cursor for next page of results",
                      "example": "team_dmU311Ajzj"
                    },
                    "total_results": {
                      "type": "number",
                      "example": 105
                    },
                    "has_more": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Clients retrieved successfully"
                    },
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "timestamp": {
                      "type": "number",
                      "example": 1768240724433
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "team_1234567890",
                      "legal_name": "MI EMPRESA EJEMPLO SA DE CV",
                      "address": {
                        "street": "Av. Paseo de la Reforma",
                        "exterior": "222",
                        "neighborhood": "Juárez",
                        "city": "Ciudad de México",
                        "state": "CDMX",
                        "zip": "06600",
                        "country": "MEX"
                      },
                      "brand": {
                        "alias": "Mi Empresa",
                        "primary_color": "#1F2937",
                        "secondary_color": "#10B981",
                        "logo": null
                      },
                      "settings": {
                        "default_description": null,
                        "emails": {
                          "invoices_bcc": [],
                          "avoid_invoice_emails": false,
                          "avoid_test_invoice_emails": true,
                          "avoid_receipts_emails": false
                        },
                        "global_invoice_disabled": false,
                        "use": "G03",
                        "periodicity": {
                          "label": "Mes",
                          "value": "month"
                        }
                      },
                      "members": [
                        {
                          "id": "user_1234567890",
                          "email": "admin@ejemplo.com",
                          "role": "admin"
                        }
                      ],
                      "owner": "user_1234567890",
                      "support_email": "soporte@ejemplo.com",
                      "support_phone": "+525512345678",
                      "tax_id": "MEE200101ABC",
                      "tax_system": "601",
                      "created_at": 1767225600000,
                      "sat": {
                        "completed": true,
                        "connected_at": 1767225600000,
                        "csd_expires_at": 1893456000000
                      },
                      "integrations": {
                        "stripe": {
                          "completed": false,
                          "category": null
                        }
                      },
                      "metadata": {},
                      "credit_limit": null,
                      "used_credits": 12,
                      "credit_period_start": 1767225600000,
                      "status": "active",
                      "scheduled_deletion": null
                    }
                  ],
                  "next": null,
                  "total_results": 1,
                  "has_more": false,
                  "message": "Clients retrieved successfully",
                  "success": true,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createTeams",
        "tags": [
          "Teams"
        ],
        "summary": "Create team",
        "description": "Create a new team.\n\nRequires the `multipleIssuerAccounts` feature on your plan → `403 insufficient_permissions` without it.\n\n**gigstack Connect:** Create teams using the `team` parameter.\n\nRequires a plan with the \"Proveedores\" feature: otherwise the call answers `401` with\n`You should subscribe to a plan that allows \"Proveedores\" feature.` (standardized envelope).\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamInput"
              },
              "example": {
                "address": {
                  "country": "MEX",
                  "street": "Av. Reforma",
                  "zip": "11000",
                  "city": "Ciudad de México",
                  "state": "CDMX",
                  "exterior": "456",
                  "municipality": "Miguel Hidalgo",
                  "neighborhood": "Polanco"
                },
                "brand": {
                  "alias": "Empresa Innovadora",
                  "primary_color": "#2563eb",
                  "secondary_color": "#1d4ed8",
                  "logo": "https://example.com/logo.png"
                },
                "support_email": "soporte@empresa.com",
                "support_phone": "+52 55 9876 5432",
                "tax_id": "EIN850123ABC",
                "tax_system": "601",
                "generate_onboarding_url": true,
                "add_members": [
                  {
                    "id": "user123abc",
                    "role": "editor"
                  },
                  {
                    "id": "user456def",
                    "role": "viewer"
                  }
                ],
                "add_master_team_members": false,
                "legal_name": "Empresa de Tecnología S.A. de C.V.",
                "credit_limit": 1000
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Team created. `onboarding_url` is included when requested with `generate_onboarding_url`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/ApiPublicTeam"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "onboarding_url": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        }
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "team_1234567890",
                    "legal_name": "MI EMPRESA EJEMPLO SA DE CV",
                    "address": {
                      "street": "Av. Paseo de la Reforma",
                      "exterior": "222",
                      "neighborhood": "Juárez",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "zip": "06600",
                      "country": "MEX"
                    },
                    "brand": {
                      "alias": "Mi Empresa",
                      "primary_color": "#1F2937",
                      "secondary_color": "#10B981",
                      "logo": null
                    },
                    "settings": {
                      "default_description": null,
                      "emails": {
                        "invoices_bcc": [],
                        "avoid_invoice_emails": false,
                        "avoid_test_invoice_emails": true,
                        "avoid_receipts_emails": false
                      },
                      "global_invoice_disabled": false,
                      "use": "G03",
                      "periodicity": {
                        "label": "Mes",
                        "value": "month"
                      }
                    },
                    "members": [
                      {
                        "id": "user_1234567890",
                        "email": "admin@ejemplo.com",
                        "role": "admin"
                      }
                    ],
                    "owner": "user_1234567890",
                    "support_email": "soporte@ejemplo.com",
                    "support_phone": "+525512345678",
                    "tax_id": "MEE200101ABC",
                    "tax_system": "601",
                    "created_at": 1767225600000,
                    "sat": {
                      "completed": true,
                      "connected_at": 1767225600000,
                      "csd_expires_at": 1893456000000
                    },
                    "integrations": {
                      "stripe": {
                        "completed": false,
                        "category": null
                      }
                    },
                    "metadata": {},
                    "credit_limit": null,
                    "used_credits": 12,
                    "credit_period_start": 1767225600000,
                    "status": "active",
                    "scheduled_deletion": null,
                    "onboarding_url": "https://embeded.gigstack.pro/?sessionId=otpOnboarding_7Kd2Pq&c=193847"
                  },
                  "message": "Team created successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Body validation failed (`validation_failed`), or `Only livemode teams are allowed to be created` (`invalid_request_body`) when called with a test key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "examples": {
                  "test_key": {
                    "summary": "Test-mode key",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Only livemode teams are allowed to be created"
                      },
                      "timestamp": 1767225600000
                    }
                  },
                  "validation": {
                    "summary": "Invalid body",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "validation_failed",
                        "message": "Request validation failed",
                        "details": [
                          "tax_id: Expected string"
                        ]
                      },
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/teams/{id}": {
      "get": {
        "operationId": "getTeamsById",
        "tags": [
          "Teams"
        ],
        "summary": "Get team",
        "description": "Retrieve a specific team by ID.\n\n**gigstack Connect:** Access other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "team_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Team retrieved. Standardized envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicTeam"
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "team_1234567890",
                    "legal_name": "MI EMPRESA EJEMPLO SA DE CV",
                    "address": {
                      "street": "Av. Paseo de la Reforma",
                      "exterior": "222",
                      "neighborhood": "Juárez",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "zip": "06600",
                      "country": "MEX"
                    },
                    "brand": {
                      "alias": "Mi Empresa",
                      "primary_color": "#1F2937",
                      "secondary_color": "#10B981",
                      "logo": null
                    },
                    "settings": {
                      "default_description": null,
                      "emails": {
                        "invoices_bcc": [],
                        "avoid_invoice_emails": false,
                        "avoid_test_invoice_emails": true,
                        "avoid_receipts_emails": false
                      },
                      "global_invoice_disabled": false,
                      "use": "G03",
                      "periodicity": {
                        "label": "Mes",
                        "value": "month"
                      }
                    },
                    "members": [
                      {
                        "id": "user_1234567890",
                        "email": "admin@ejemplo.com",
                        "role": "admin"
                      }
                    ],
                    "owner": "user_1234567890",
                    "support_email": "soporte@ejemplo.com",
                    "support_phone": "+525512345678",
                    "tax_id": "MEE200101ABC",
                    "tax_system": "601",
                    "created_at": 1767225600000,
                    "sat": {
                      "completed": true,
                      "connected_at": 1767225600000,
                      "csd_expires_at": 1893456000000
                    },
                    "integrations": {
                      "stripe": {
                        "completed": false,
                        "category": null
                      }
                    },
                    "metadata": {},
                    "credit_limit": null,
                    "used_credits": 12,
                    "credit_period_start": 1767225600000,
                    "status": "active",
                    "scheduled_deletion": null
                  },
                  "message": "Team retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "put": {
        "operationId": "updateTeamsById",
        "tags": [
          "Teams"
        ],
        "summary": "Update team",
        "description": "Update an existing team.\n\n**gigstack Connect:** Update other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "team_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamInput"
              },
              "example": {
                "address": {
                  "country": "MEX",
                  "street": "Av. Reforma (Updated)",
                  "zip": "11000",
                  "city": "Ciudad de México",
                  "state": "CDMX",
                  "exterior": "456-B",
                  "municipality": "Miguel Hidalgo",
                  "neighborhood": "Polanco"
                },
                "brand": {
                  "alias": "Empresa Innovadora 2025",
                  "primary_color": "#1e40af",
                  "secondary_color": "#1e3a8a",
                  "logo": "https://example.com/new-logo.png"
                },
                "support_email": "soporte@empresa.com",
                "support_phone": "+52 55 9876 5432",
                "tax_id": "EIN850123ABC",
                "tax_system": "601"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated. Raw body (no `success`/`timestamp`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data"
                  ],
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicTeam"
                    }
                  }
                },
                "example": {
                  "message": "Team updated successfully",
                  "data": {
                    "id": "team_1234567890",
                    "legal_name": "MI EMPRESA EJEMPLO SA DE CV",
                    "address": {
                      "street": "Av. Paseo de la Reforma",
                      "exterior": "222",
                      "neighborhood": "Juárez",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "zip": "06600",
                      "country": "MEX"
                    },
                    "brand": {
                      "alias": "Mi Empresa",
                      "primary_color": "#1F2937",
                      "secondary_color": "#10B981",
                      "logo": null
                    },
                    "settings": {
                      "default_description": null,
                      "emails": {
                        "invoices_bcc": [],
                        "avoid_invoice_emails": false,
                        "avoid_test_invoice_emails": true,
                        "avoid_receipts_emails": false
                      },
                      "global_invoice_disabled": false,
                      "use": "G03",
                      "periodicity": {
                        "label": "Mes",
                        "value": "month"
                      }
                    },
                    "members": [
                      {
                        "id": "user_1234567890",
                        "email": "admin@ejemplo.com",
                        "role": "admin"
                      }
                    ],
                    "owner": "user_1234567890",
                    "support_email": "soporte@ejemplo.com",
                    "support_phone": "+525512345678",
                    "tax_id": "MEE200101ABC",
                    "tax_system": "601",
                    "created_at": 1767225600000,
                    "sat": {
                      "completed": true,
                      "connected_at": 1767225600000,
                      "csd_expires_at": 1893456000000
                    },
                    "integrations": {
                      "stripe": {
                        "completed": false,
                        "category": null
                      }
                    },
                    "metadata": {},
                    "credit_limit": null,
                    "used_credits": 12,
                    "credit_period_start": 1767225600000,
                    "status": "active",
                    "scheduled_deletion": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Body validation failed. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": "Invalid request body",
                  "errors": [
                    {
                      "path": "email",
                      "code": "invalid_type",
                      "message": "Field is reserved and cannot be updated"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Failed to update team"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTeamsById",
        "tags": [
          "Teams"
        ],
        "summary": "Delete team",
        "description": "Schedule a team for deletion (soft delete).\n\nThe team's `status` is set to `pending_deletion` and a hard deletion is scheduled **30 days** from now.\nDuring this grace period the team is retained for recovery purposes. All members are removed from the team,\nand each member's `teams` array is updated accordingly. A member's `billingAccount` is cleared when no\nother team of theirs shares it.\n\nRequires the `multipleIssuerAccounts` feature on your plan → `403 insufficient_permissions` without it.\n\n## Preconditions\n\nThe team **cannot** be deleted when any of the following are true:\n\n- The team already has `status = pending_deletion` → `409 resource_conflict`.\n- The team has existing `invoices`, `payments`, or `receipts` → `400 business_rule_violation`.\n- The team has any active integration (`completed = true`) among:\n  `stripe`, `mercadopago`, `paypal`, `openpay`, `conekta`, `clip`, `bank`, `shopify`, `whmcs`, `hilos`\n  → `400 business_rule_violation`.\n\n**gigstack Connect:** Delete other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Team ID",
            "example": "team_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Team scheduled for deletion",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "message": {
                          "example": "Team scheduled for deletion"
                        },
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "example": "team_1234567890"
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "pending_deletion"
                              ],
                              "example": "pending_deletion"
                            },
                            "scheduled_deletion": {
                              "type": "object",
                              "properties": {
                                "date": {
                                  "type": "integer",
                                  "format": "int64",
                                  "description": "Unix timestamp (ms) when hard deletion will occur (≈30 days from now)",
                                  "example": 1779984000000
                                },
                                "flagged_at": {
                                  "type": "integer",
                                  "format": "int64",
                                  "description": "Unix timestamp (ms) when the team was scheduled for deletion",
                                  "example": 1777392000000
                                },
                                "flagged_by": {
                                  "type": "string",
                                  "description": "User ID that scheduled the deletion",
                                  "example": "user_abc123"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "team_1234567890",
                    "status": "pending_deletion",
                    "scheduled_deletion": {
                      "date": 1769817600000,
                      "flagged_at": 1767225600000,
                      "flagged_by": "user_1234567890"
                    }
                  },
                  "message": "Team scheduled for deletion",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - The team has blocking resources (invoices/payments/receipts) or active integrations\nthat must be removed or disconnected before deletion.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "blockingResources": {
                    "summary": "Team has existing resources",
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Team has existing resources that must be removed before deletion"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "activeIntegrations": {
                    "summary": "Team has active integrations",
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Team has active integrations that must be disconnected before deletion"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "409": {
            "description": "Team is already pending deletion",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": {
                    "code": "invalid_request_body",
                    "message": "Team is already pending deletion"
                  },
                  "success": false,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/teams/integrations": {
      "get": {
        "tags": [
          "Teams"
        ],
        "summary": "Get team integrations (not implemented)",
        "operationId": "getTeamIntegrations",
        "description": "**Not yet available.** The route is registered and reachable — it is declared before\n`/teams/{id}` so it is no longer shadowed by the team-lookup route — but the handler is\nstill a stub that returns `501 Not Implemented` for every request. It never returns\nintegration data.\n\nDo not build against this endpoint yet. This entry exists so the published surface\nmatches the deployed behavior.\n",
        "deprecated": false,
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "501": {
            "description": "Not implemented. The body is raw (no standardized envelope).\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "enum": [
                        "Not implemented"
                      ],
                      "example": "Not implemented"
                    }
                  }
                },
                "example": {
                  "message": "Not implemented"
                }
              }
            }
          }
        }
      }
    },
    "/teams/{id}/add-member": {
      "post": {
        "operationId": "createTeamsByIdAddMember",
        "tags": [
          "Teams"
        ],
        "summary": "Add team member",
        "description": "Add a member to a team.\n\n**gigstack Connect:** Add members to other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "team_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "User ID to add as a team member",
                    "example": "user123abc"
                  },
                  "role": {
                    "type": "string",
                    "description": "Role for the team member. Defaults to 'viewer' if not specified.",
                    "enum": [
                      "admin",
                      "editor",
                      "viewer"
                    ],
                    "default": "viewer",
                    "example": "editor"
                  },
                  "ghost": {
                    "type": "boolean",
                    "description": "When true, the member is hidden from the team members list in the dashboard.\nGhost members have full access based on their role but are invisible to other team members.\nUseful for platform partners that need persistent, hidden access to managed teams.\n",
                    "default": false,
                    "example": true
                  }
                }
              },
              "example": {
                "id": "user123abc",
                "role": "editor",
                "ghost": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Team member added successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "user_9876543210",
                    "role": "member",
                    "isAdmin": false,
                    "payments": "member",
                    "receipts": "member"
                  },
                  "message": "Member added to team",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/teams/{id}/remove-member": {
      "post": {
        "operationId": "createTeamsByIdRemoveMember",
        "tags": [
          "Teams"
        ],
        "summary": "Remove team member",
        "description": "Remove a member from a team.\n\n**gigstack Connect:** Remove members from other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "team_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Id of the user to remove from the team."
                  }
                }
              },
              "example": {
                "id": "user_9876543210"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member removed. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "message": "User removed successfully from team"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body (`Invalid request body`, with `errors`), or `User is not a member of the team`. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": "User is not a member of the team"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`User not found` or `Team not found`. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "User not found"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/teams/{id}/series": {
      "get": {
        "operationId": "getTeamsByIdSeries",
        "tags": [
          "Teams"
        ],
        "summary": "Get team series",
        "description": "Get series for a team.\n\n**gigstack Connect:** Get series for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "team_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Series and their last folio per mode. Raw body. For all series, `data` is an array of `{ series, live, test }` (last folio used); for a single series it is one object with `currentFolio` / `nextFolio` per mode.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "oneOf": [
                        {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "series": {
                                "type": "string"
                              },
                              "live": {
                                "type": "integer"
                              },
                              "test": {
                                "type": "integer"
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "properties": {
                            "series": {
                              "type": "string"
                            },
                            "live": {
                              "type": "object",
                              "properties": {
                                "currentFolio": {
                                  "type": "integer"
                                },
                                "nextFolio": {
                                  "type": "integer"
                                }
                              }
                            },
                            "test": {
                              "type": "object",
                              "properties": {
                                "currentFolio": {
                                  "type": "integer"
                                },
                                "nextFolio": {
                                  "type": "integer"
                                }
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "series": "A",
                      "live": 123,
                      "test": 7
                    },
                    {
                      "series": "P",
                      "live": 45,
                      "test": 0
                    }
                  ],
                  "message": "Series data retrieved successfully"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createTeamsByIdSeries",
        "tags": [
          "Teams"
        ],
        "summary": "Create team series",
        "description": "Create a series for a team.\n\n**gigstack Connect:** Create series for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "team_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "series": {
                    "type": "string",
                    "description": "Series identifier (alphanumeric, max 10 characters)",
                    "example": "B"
                  },
                  "live": {
                    "type": "number",
                    "nullable": true,
                    "description": "Initial folio number for live mode",
                    "default": 0,
                    "example": 1000
                  },
                  "test": {
                    "type": "number",
                    "nullable": true,
                    "description": "Initial folio number for test mode",
                    "default": 0,
                    "example": 1
                  }
                },
                "required": [
                  "series"
                ]
              },
              "example": {
                "series": "B",
                "live": 1000,
                "test": 1
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Series created. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data"
                  ],
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "series": {
                          "type": "string"
                        },
                        "live": {
                          "type": "object",
                          "properties": {
                            "currentFolio": {
                              "type": "integer"
                            },
                            "nextFolio": {
                              "type": "integer"
                            }
                          }
                        },
                        "test": {
                          "type": "object",
                          "properties": {
                            "currentFolio": {
                              "type": "integer"
                            },
                            "nextFolio": {
                              "type": "integer"
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "series": "A",
                    "live": {
                      "currentFolio": 0,
                      "nextFolio": 1
                    },
                    "test": {
                      "currentFolio": 0,
                      "nextFolio": 1
                    }
                  },
                  "message": "Series created successfully"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/teams/{id}/series/{seriesId}": {
      "put": {
        "operationId": "updateTeamsByIdSeriesBySeriesId",
        "tags": [
          "Teams"
        ],
        "summary": "Update team series",
        "description": "Update a team series.\n\n**gigstack Connect:** Update series for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "team_1234567890"
          },
          {
            "name": "seriesId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "series_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "live": {
                    "type": "number",
                    "nullable": true,
                    "description": "Update folio number for live mode",
                    "example": 2000
                  },
                  "test": {
                    "type": "number",
                    "nullable": true,
                    "description": "Update folio number for test mode",
                    "example": 50
                  }
                },
                "description": "At least one of live or test must be provided"
              },
              "example": {
                "live": 2000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Folio counters updated. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data"
                  ],
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "series": {
                          "type": "string"
                        },
                        "live": {
                          "type": "object",
                          "properties": {
                            "currentFolio": {
                              "type": "integer"
                            },
                            "nextFolio": {
                              "type": "integer"
                            }
                          }
                        },
                        "test": {
                          "type": "object",
                          "properties": {
                            "currentFolio": {
                              "type": "integer"
                            },
                            "nextFolio": {
                              "type": "integer"
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": {
                    "series": "A",
                    "live": {
                      "currentFolio": 123,
                      "nextFolio": 124
                    },
                    "test": {
                      "currentFolio": 7,
                      "nextFolio": 8
                    }
                  },
                  "message": "Series folio numbers updated successfully"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/teams/{id}/settings": {
      "put": {
        "operationId": "updateTeamsByIdSettings",
        "tags": [
          "Teams"
        ],
        "summary": "Update team settings",
        "description": "Update team settings including defaults for invoicing, taxes, series, and email configurations.\n\n**gigstack Connect:** Update settings for other teams using the `team` parameter.\n\n## Team Settings Configuration\n\nThis endpoint allows you to configure various team-wide defaults and behaviors:\n\n- **Invoice Settings:** Default descriptions, PDF notes, product keys\n- **Tax Configuration:** Default taxes for MXN and USD currencies\n- **Email Settings:** BCC recipients, email preferences\n- **CFDI Configuration:** Default series, uses, product/unit keys\n- **Automation:** Payment complement automation for PPD invoices\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Team ID",
            "example": "team_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamSettingsInput"
              },
              "example": {
                "keep_full_legal_name": false,
                "default_description": "Professional consulting services",
                "invoice_pdf_notes": "Thank you for your business",
                "product_key": "80141503",
                "unit_key": "E48",
                "use": "G03",
                "periodicity": "month",
                "emails": {
                  "invoices_bcc": [
                    "admin@company.com"
                  ],
                  "avoid_invoice_emails": false
                },
                "default_series": {
                  "income": {
                    "serie": "A",
                    "folio_number_live": 1001,
                    "folio_number_test": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings saved; `data` is the whole team. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data"
                  ],
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicTeam"
                    }
                  }
                },
                "example": {
                  "message": "Team settings updated",
                  "data": {
                    "id": "team_1234567890",
                    "legal_name": "MI EMPRESA EJEMPLO SA DE CV",
                    "address": {
                      "street": "Av. Paseo de la Reforma",
                      "exterior": "222",
                      "neighborhood": "Juárez",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "zip": "06600",
                      "country": "MEX"
                    },
                    "brand": {
                      "alias": "Mi Empresa",
                      "primary_color": "#1F2937",
                      "secondary_color": "#10B981",
                      "logo": null
                    },
                    "settings": {
                      "default_description": null,
                      "emails": {
                        "invoices_bcc": [],
                        "avoid_invoice_emails": false,
                        "avoid_test_invoice_emails": true,
                        "avoid_receipts_emails": false
                      },
                      "global_invoice_disabled": false,
                      "use": "G03",
                      "periodicity": {
                        "label": "Mes",
                        "value": "month"
                      }
                    },
                    "members": [
                      {
                        "id": "user_1234567890",
                        "email": "admin@ejemplo.com",
                        "role": "admin"
                      }
                    ],
                    "owner": "user_1234567890",
                    "support_email": "soporte@ejemplo.com",
                    "support_phone": "+525512345678",
                    "tax_id": "MEE200101ABC",
                    "tax_system": "601",
                    "created_at": 1767225600000,
                    "sat": {
                      "completed": true,
                      "connected_at": 1767225600000,
                      "csd_expires_at": 1893456000000
                    },
                    "integrations": {
                      "stripe": {
                        "completed": false,
                        "category": null
                      }
                    },
                    "metadata": {},
                    "credit_limit": null,
                    "used_credits": 12,
                    "credit_period_start": 1767225600000,
                    "status": "active",
                    "scheduled_deletion": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid settings data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/teams/{id}/onboarding-url": {
      "get": {
        "operationId": "getTeamsByIdOnboardingUrl",
        "tags": [
          "Teams"
        ],
        "summary": "Get team onboarding URL",
        "description": "Generate a secure onboarding URL for team setup and configuration.\n\n**Important:** This endpoint is only available for gigstack Connect accounts (master teams).\n\n## Use Cases\n- Generate onboarding links for new teams\n- Allow secure team configuration setup\n- Enable embedded team management flows\n\n**gigstack Connect:** Generate onboarding URLs for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Team ID to generate onboarding URL for",
            "example": "team_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Onboarding URL generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "string",
                      "example": "https://embeded.gigstack.pro/?sessionId=otpOnboarding_abc123&c=secure_token",
                      "description": "Secure onboarding URL with session ID and code"
                    },
                    "message": {
                      "type": "string",
                      "example": "Onboarding URL generated successfully"
                    }
                  }
                },
                "example": {
                  "data": "https://embeded.gigstack.pro/?sessionId=otpOnboarding_7Kd2Pq&c=193847",
                  "message": "Onboarding URL retrieved successfully"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Only available for master teams",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Unauthorized"
                    },
                    "error": {
                      "type": "string",
                      "example": "Unauthorized endpoint only available for connect accounts"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        }
      }
    },
    "/teams/{id}/portal-access-token": {
      "post": {
        "operationId": "createTeamsByIdPortalAccessToken",
        "tags": [
          "Teams"
        ],
        "summary": "Create a portal access token",
        "description": "Mint a short-lived, read-only access token for the team's public portal, and get a ready-to-share magic link.\n\nThe link opens the gigstack public portal (embeded.gigstack.pro) where the team can list and download its issued live-mode invoices, branded with your master team's logo and colors. The token cannot create, modify or cancel anything, and it only grants the scopes you request.\n\n**Important:** Minting a token for a team other than your own is only available for gigstack Connect accounts (master teams), and the target team must belong to your billing account.\n\n## Use Cases\n- Embed an \"invoices\" section for your sub-teams inside your own product\n- Generate on-demand links so a sub-team can review its issued invoices without a gigstack login\n\n## Recommendations\n- Generate the link at click time and redirect the user to it; do not store it or send it by email\n- Use the default 1h expiry unless you have a longer-lived embedded session\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Team ID to mint the portal access token for",
            "example": "team_1234567890"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expiresIn": {
                    "type": "string",
                    "default": "1h",
                    "description": "Token lifetime as <integer>[s|m|h|d] or an integer number of seconds. Maximum 24h.",
                    "example": "1h"
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "invoices:read"
                      ]
                    },
                    "default": [
                      "invoices:read"
                    ],
                    "description": "Scopes to grant. Only invoices:read is supported today; more resources will be added."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Portal access token created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "Signed read-only JWT. Send it as the t query parameter of the portal URL."
                    },
                    "url": {
                      "type": "string",
                      "example": "https://embeded.gigstack.pro/facturas?t=eyJhbGciOi...",
                      "description": "Ready-to-share portal link for the team"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2026-08-13T21:30:00.000Z",
                      "description": "Token expiration in ISO 8601"
                    }
                  }
                },
                "example": {
                  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.<payload>.<signature>",
                  "url": "https://embeded.gigstack.pro/facturas?t=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.%3Cpayload%3E.%3Csignature%3E",
                  "expiresAt": "2026-01-08T00:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid expiresIn or unsupported scope",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "invalid_expires_in",
                        "expires_in_too_long",
                        "unsupported_scope",
                        "invalid_team_id"
                      ]
                    },
                    "message": {
                      "type": "string",
                      "example": "expiresIn cannot exceed 24h"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The requested team does not belong to your account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "forbidden_team"
                    },
                    "message": {
                      "type": "string",
                      "example": "The requested team does not belong to your account"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          }
        }
      }
    },
    "/teams/{id}/sat-connection": {
      "post": {
        "operationId": "createTeamsByIdSatConnection",
        "tags": [
          "Teams"
        ],
        "summary": "Upload SAT CSD certificates",
        "description": "Upload SAT CSD (Certificado de Sello Digital) certificates to establish SAT connection for CFDI invoicing.\n\nThis endpoint accepts multipart form data with the certificate files and password.\n\n## Required Files\n- **cert**: Certificate file (.cer) - The public certificate\n- **key**: Private key file (.key) - The encrypted private key\n- **keyPass**: Password for the private key\n\n## First-Time Connection\nWhen this is the first SAT connection for a team (no previous SAT setup),\nthe system will automatically initialize default invoice series (G, NC, P, T).\n\n**gigstack Connect:** Upload SAT certificates for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Team ID to upload SAT certificates for",
            "example": "team_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "cert": {
                    "type": "string",
                    "format": "binary",
                    "description": "Certificate file (.cer)"
                  },
                  "key": {
                    "type": "string",
                    "format": "binary",
                    "description": "Private key file (.key)"
                  },
                  "keyPass": {
                    "type": "string",
                    "description": "Password for the private key"
                  }
                },
                "required": [
                  "cert",
                  "key",
                  "keyPass"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SAT connection established successfully",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "isValid": {
                              "type": "boolean",
                              "example": true
                            },
                            "details": {
                              "type": "object",
                              "properties": {
                                "serialNumber": {
                                  "type": "string",
                                  "example": "30001000000500003416"
                                },
                                "validTo": {
                                  "type": "number",
                                  "example": 1735689600000
                                }
                              }
                            }
                          }
                        },
                        "message": {
                          "example": "SAT connection established successfully"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "isValid": true,
                    "details": {
                      "subject": "CN=MI EMPRESA EJEMPLO SA DE CV, x500UniqueIdentifier=MEE200101ABC",
                      "issuer": "CN=AC UAT, O=SERVICIO DE ADMINISTRACION TRIBUTARIA",
                      "validFrom": 1767225600000,
                      "validTo": 1893456000000,
                      "serialNumber": "30001000000500003416",
                      "fingerprint": "A1:B2:C3:D4:E5:F6:07:18:29:3A:4B:5C:6D:7E:8F:90:A1:B2:C3:D4",
                      "fingerprint256": "A1:B2:C3:D4:E5:F6:07:18:29:3A:4B:5C:6D:7E:8F:90:A1:B2:C3:D4:E5:F6:07:18:29:3A:4B:5C:6D:7E:8F:90"
                    }
                  },
                  "message": "SAT connection established successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Missing files or invalid certificate",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden - Team not in same billing account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/teams/{id}/manifest/sign": {
      "post": {
        "operationId": "createTeamsByIdManifestSign",
        "tags": [
          "Teams"
        ],
        "summary": "Sign manifest document",
        "description": "Signs a manifest document (Carta Manifiesto) using the FIEL (Firma Electrónica Avanzada) for SAT compliance.\n\nThis endpoint is used to sign the authorization manifest that authorizes the PAC (Proveedor Autorizado de Certificación)\nto issue CFDI invoices on behalf of your team's RFC. The manifest must be signed to grant the PAC permission to stamp\nand process invoices under your team's tax identification.\n\n**Important Notes:**\n- Your SAT configuration must be completed before signing the manifest\n- The FIEL certificate must be valid and issued by SAT\n- The certificate must match your team's RFC\n- Once signed, the manifest is stored in your team's SAT configuration\n- The manifest includes both XML and PDF files\n\n**Supported Formats:**\n\n1. **JSON format (application/json):**\n   - Send Base64 encoded certificate files\n   - Useful for API integrations\n\n2. **Form Data format (multipart/form-data):**\n   - Upload certificate files directly\n   - Useful for web form submissions\n\n**Note:** The `team` and `livemode` parameters are automatically extracted from your JWT token and applied to the request.\nYou do not need to include these fields in the request body.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Team ID to sign manifest for",
            "example": "team_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "key",
                  "cert",
                  "password"
                ],
                "properties": {
                  "key": {
                    "type": "string",
                    "description": "Base64 encoded FIEL .key file",
                    "example": "MIIFDjBABgkqhkiG9w0BBQ0wMz..."
                  },
                  "cert": {
                    "type": "string",
                    "description": "Base64 encoded FIEL .cer file",
                    "example": "MIIFuzCCA6OgAwIBAgIUMzAwMD..."
                  },
                  "password": {
                    "type": "string",
                    "format": "password",
                    "description": "FIEL password (private key password)",
                    "example": "my_secure_password"
                  }
                }
              },
              "examples": {
                "basic": {
                  "summary": "Basic manifest signing request",
                  "value": {
                    "key": "MIIFDjBABgkqhkiG9w0BBQ0wMz...",
                    "cert": "MIIFuzCCA6OgAwIBAgIUMzAwMD...",
                    "password": "my_secure_password"
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "key",
                  "cert",
                  "password"
                ],
                "properties": {
                  "key": {
                    "type": "string",
                    "format": "binary",
                    "description": "FIEL .key file upload"
                  },
                  "cert": {
                    "type": "string",
                    "format": "binary",
                    "description": "FIEL .cer file upload"
                  },
                  "password": {
                    "type": "string",
                    "description": "FIEL password (private key password)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Manifest signed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Manifest signed successfully"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "xmlBase64": {
                          "type": "string",
                          "description": "Base64 encoded signed manifest XML"
                        },
                        "pdfBase64": {
                          "type": "string",
                          "description": "Base64 encoded manifest PDF"
                        },
                        "fechaFirma": {
                          "type": "string",
                          "format": "date-time",
                          "description": "Signature date and time",
                          "example": "2024-01-08T15:30:00.000Z"
                        },
                        "mensajeResultado": {
                          "type": "string",
                          "description": "Result message from signing service",
                          "example": "Firma exitosa"
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "success": {
                    "summary": "Successful manifest signing",
                    "value": {
                      "message": "Manifest signed successfully",
                      "data": {
                        "xmlBase64": "PD94bWwgdmVyc2lvbj0iMS4wIi...",
                        "pdfBase64": "JVBERi0xLjQKJeLjz9MKMyAwIG...",
                        "fechaFirma": "2024-01-08T15:30:00.000Z",
                        "mensajeResultado": "Firma exitosa"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input or validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_field": {
                    "summary": "Missing required field",
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Bad Request"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "invalid_certificate": {
                    "summary": "Invalid FIEL certificate",
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Bad Request"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "certificate_mismatch": {
                    "summary": "Certificate RFC mismatch",
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Bad Request"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "sat_incomplete": {
                    "summary": "SAT configuration incomplete",
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Bad Request"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "signing_failed": {
                    "summary": "Manifest signing failed",
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "CFDI Service Error"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Team not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "team_not_found": {
                    "summary": "Team not found",
                    "value": {
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Not Found"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/users": {
      "get": {
        "operationId": "listUsers",
        "tags": [
          "Users"
        ],
        "summary": "List users",
        "description": "Retrieve a paginated list of users.\n\n**gigstack Connect:** Access other teams' users using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/NextParam"
          },
          {
            "$ref": "#/components/parameters/OrderByParam"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLteParam"
          },
          {
            "$ref": "#/components/parameters/CreatedGtParam"
          },
          {
            "$ref": "#/components/parameters/CreatedLtParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Users retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                },
                "example": {
                  "success": true,
                  "message": "Users retrieved successfully",
                  "data": [
                    {
                      "id": "user_1234567890",
                      "email": "admin@ejemplo.com",
                      "first_name": "Ana",
                      "last_name": "López",
                      "phone": "+525512345678",
                      "teams": [
                        "team_1234567890"
                      ],
                      "created_at": 1767225600000,
                      "company_role": "Contadora",
                      "address": {
                        "street": "Av. Paseo de la Reforma",
                        "exterior": "222",
                        "neighborhood": "Juárez",
                        "city": "Ciudad de México",
                        "state": "CDMX",
                        "zip": "06600",
                        "country": "MEX"
                      }
                    }
                  ],
                  "next": null,
                  "has_more": false,
                  "total_results": 1,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createUsers",
        "tags": [
          "Users"
        ],
        "summary": "Create user",
        "description": "Create a new user.\n\n**gigstack Connect:** Create users for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserInput"
              },
              "example": {
                "email": "maria.gonzalez@empresa.com",
                "first_name": "María",
                "last_name": "González",
                "phone": "+52 55 2345 6789",
                "company_role": "Gerente de Ventas",
                "address": {
                  "country": "MEX",
                  "street": "Calle Morelos",
                  "zip": "06000",
                  "city": "Ciudad de México",
                  "state": "CDMX",
                  "exterior": "789",
                  "neighborhood": "Centro"
                },
                "auto_join": true,
                "role": "editor"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User created. Standardized envelope with the new user in `data`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "message": {
                      "type": "string",
                      "example": "User created"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicUser"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "user_1234567890",
                    "email": "admin@ejemplo.com",
                    "first_name": "Ana",
                    "last_name": "López",
                    "phone": "+525512345678",
                    "teams": [
                      "team_1234567890"
                    ],
                    "created_at": 1767225600000,
                    "company_role": "Contadora",
                    "address": {
                      "street": "Av. Paseo de la Reforma",
                      "exterior": "222",
                      "neighborhood": "Juárez",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "zip": "06600",
                      "country": "MEX"
                    }
                  },
                  "message": "User created",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Two shapes:\n- Body validation failure: standardized envelope, `error.code: validation_failed`, message `Invalid body`.\n- Rejected by the identity provider: raw `{ \"error\", \"message\" }` body. `error` is one of\n  `Email already exists`, `Invalid phone number` (phone must be E.164, e.g. `+525512345678`),\n  `Invalid email`, `Validation error`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/StandardErrorResponse"
                    },
                    {
                      "type": "object",
                      "required": [
                        "error",
                        "message"
                      ],
                      "properties": {
                        "error": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "email_exists": {
                    "summary": "Email already registered",
                    "value": {
                      "error": "Email already exists",
                      "message": "A user with this email already exists"
                    }
                  },
                  "invalid_phone": {
                    "summary": "Phone not in E.164",
                    "value": {
                      "error": "Invalid phone number",
                      "message": "Phone number must be in E.164 format (e.g., +1234567890)"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/users/{id}": {
      "get": {
        "operationId": "getUsersById",
        "tags": [
          "Users"
        ],
        "summary": "Get user",
        "description": "Retrieve a specific user by ID.\n\n**gigstack Connect:** Access other teams' users using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "user_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "User retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardSuccessResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "user_1234567890",
                    "email": "admin@ejemplo.com",
                    "first_name": "Ana",
                    "last_name": "López",
                    "phone": "+525512345678",
                    "teams": [
                      "team_1234567890"
                    ],
                    "created_at": 1767225600000,
                    "company_role": "Contadora",
                    "address": {
                      "street": "Av. Paseo de la Reforma",
                      "exterior": "222",
                      "neighborhood": "Juárez",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "zip": "06600",
                      "country": "MEX"
                    }
                  },
                  "message": "User retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "put": {
        "operationId": "updateUsersById",
        "tags": [
          "Users"
        ],
        "summary": "Update user",
        "description": "Update an existing user.\n\n**gigstack Connect:** Update other teams' users using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "user_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserInput"
              },
              "example": {
                "first_name": "María Fernanda",
                "last_name": "González López",
                "phone": "+52 55 2345 6789",
                "company_role": "Gerente Regional de Ventas",
                "address": {
                  "country": "MEX",
                  "street": "Calle Morelos (Oficina Nueva)",
                  "zip": "06000",
                  "city": "Ciudad de México",
                  "state": "CDMX",
                  "exterior": "789-A",
                  "neighborhood": "Centro"
                },
                "auto_join": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated. Raw body (no `success`/`timestamp`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data"
                  ],
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicUser"
                    }
                  }
                },
                "example": {
                  "message": "User updated successfully",
                  "data": {
                    "id": "user_1234567890",
                    "email": "admin@ejemplo.com",
                    "first_name": "Ana",
                    "last_name": "López",
                    "phone": "+525512345678",
                    "teams": [
                      "team_1234567890"
                    ],
                    "created_at": 1767225600000,
                    "company_role": "Contadora",
                    "address": {
                      "street": "Av. Paseo de la Reforma",
                      "exterior": "222",
                      "neighborhood": "Juárez",
                      "city": "Ciudad de México",
                      "state": "CDMX",
                      "zip": "06600",
                      "country": "MEX"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Body validation failed. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": "Invalid request body",
                  "errors": [
                    {
                      "path": "email",
                      "code": "invalid_type",
                      "message": "Field is reserved and cannot be updated"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The resource belongs to another team, or its `livemode` does not match the API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure. Raw body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Failed to update user"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Users"
        ],
        "summary": "Delete user",
        "operationId": "deleteUser",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nRemove a user from your teams, and delete their account when it is yours.\n\nThe user must be a member of the team the request is authenticated for. They are removed\nfrom every team of your billing account you administer: your own team, and (for a\nmaster-team API key, or a dashboard admin) its sibling teams. Memberships in teams you\ndo not administer are left untouched.\n\nThe login (Firebase Auth) and the `users/{id}` document are deleted only when that\nleaves the user in no team at all **and** the account belongs to your billing account\n(created by it, or tied to no other billing account, and not the owner of one). Otherwise\nthe user keeps their login, and `account_deleted` is `false`. An Auth deletion failure is\nlogged but does not fail the request.\n\n**You cannot delete yourself.** If the id matches the user behind the API key the call\nis rejected with `400` / `business_rule_violation`.\n\n**gigstack Connect:** Delete other teams' users using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id of the user to delete.",
            "schema": {
              "type": "string"
            },
            "example": "user_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "User deleted successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "required": [
                            "id",
                            "deleted",
                            "account_deleted",
                            "removed_from_teams"
                          ],
                          "properties": {
                            "id": {
                              "type": "string",
                              "example": "user_1234567890"
                            },
                            "deleted": {
                              "type": "boolean",
                              "description": "The user is no longer in any of your teams.",
                              "enum": [
                                true
                              ],
                              "example": true
                            },
                            "account_deleted": {
                              "type": "boolean",
                              "description": "The login and user document were deleted as well.",
                              "example": true
                            },
                            "removed_from_teams": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "example": [
                                "team_1234567890"
                              ]
                            }
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "message": "User deleted successfully",
                  "timestamp": 1767225600000,
                  "data": {
                    "id": "user_1234567890",
                    "deleted": true,
                    "account_deleted": true,
                    "removed_from_teams": [
                      "team_1234567890"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "`error.code: business_rule_violation` — `Cannot delete yourself`\n(`Users cannot delete their own account through the API`), or\n`error.code: resource_access_failed` when the user cannot be accessed.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "business_rule_violation",
                    "message": "Cannot delete yourself",
                    "details": "Users cannot delete their own account through the API"
                  },
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The caller has no billing account, or (dashboard) is not an admin of the team.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "User not found, or not a member of the team the request is authenticated for.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "`Failed to delete user`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/users/reset-password/{id}": {
      "post": {
        "tags": [
          "Users"
        ],
        "summary": "Reset user password",
        "operationId": "resetUserPassword",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nGenerate a Firebase password-reset link for the user and email it to them.\n\nThe user id goes in the **path** — the only registered route is\n`POST /v2/users/reset-password/{id}`. There is no body-based variant, and the request\nbody is ignored entirely.\n\n**gigstack Connect:** Reset passwords for other teams' users using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id of the user whose password should be reset.",
            "schema": {
              "type": "string"
            },
            "example": "user_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Reset email sent. **Raw legacy shape** — `{ \"message\": \"User password reset successfully\" }`,\nwith no `success`, `data` or `timestamp`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "User password reset successfully"
                    }
                  }
                },
                "example": {
                  "message": "User password reset successfully"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized. Raw shape with only a `message` key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The user does not belong to a team the API key can access — raw shape.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`{ \"message\": \"User not found\" }` — the user is missing from Firestore or from Firebase Auth.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "`{ \"error\": \"Failed to reset user password\" }`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyErrorResponse"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/users/login-link": {
      "post": {
        "operationId": "createUsersLoginLink",
        "tags": [
          "Users"
        ],
        "summary": "Generate login link",
        "description": "Generate a login link for a user. The link contains a custom Firebase token that allows the user to authenticate directly.\n\n**Requirements:**\n- User must have been created via API (`from: 'api'`)\n- User must belong to the billing account making the request\n\nIf requirements are not met, returns a 404 error.\n\n**gigstack Connect:** Generate login links for other teams' users using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_id"
                ],
                "properties": {
                  "user_id": {
                    "type": "string",
                    "description": "The Firebase UID of the user",
                    "example": "abc123xyz"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Single-use login link, valid for one hour. Standardized envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "login_link": {
                          "type": "string"
                        },
                        "valid_until": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "method": {
                          "type": "string",
                          "enum": [
                            "token"
                          ]
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": {
                    "login_link": "https://app.gigstack.pro/auth/token-login?token=<single-use-token>",
                    "valid_until": 1767229200000,
                    "method": "token"
                  },
                  "message": "Login link generated",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "User not found or not accessible via API",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks",
        "description": "Retrieve all configured webhooks for your team.\n\n**gigstack Connect:** Access other teams' webhooks using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of webhooks to return (default 10, max 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 10
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter webhooks by status",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "inactive"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhooks retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Webhooks retrieved successfully"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiPublicWebhook"
                      }
                    },
                    "timestamp": {
                      "type": "number",
                      "example": 1709090576567
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Webhooks retrieved successfully",
                  "data": [
                    {
                      "id": "wh_dyS2ZVTj",
                      "url": "https://webhook.site/7cd05529-40fe-4c98-88e5-761de9c5feb1",
                      "events": [
                        "payment.created",
                        "payment.succeeded",
                        "invoice.created"
                      ],
                      "status": "active",
                      "description": "Production payment notifications",
                      "owner": "8UWdgXELUhf022vuoq249mtGytG2",
                      "created_at": 1709090576567
                    }
                  ],
                  "timestamp": 1709090576567
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "Create webhook",
        "description": "Create a new webhook endpoint to receive event notifications.\n\nThe response includes the webhook's signing `secret`. **It is shown only once**, so store it\nimmediately. It signs only `sat.invoice.synced` and `invoice_batch.completed` deliveries, in the\n`X-Gigstack-Signature` header (`sha256=` + hex HMAC-SHA256 of the raw body). Resource events are not\nsigned with it. There is\nno endpoint to reveal or rotate the secret later; if you lose it, delete the webhook and create\na new one.\n\nWebhooks created here send resource events in the `v1` format unless your team's default is\n`v2`. Delivery formats, headers and retry behavior are described in the `webhookEvent` callback\nbelow.\n\n**gigstack Connect:** Create webhooks for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookInput"
              },
              "example": {
                "url": "https://your-domain.com/webhooks/gigstack",
                "events": [
                  "payment.created",
                  "payment.succeeded"
                ],
                "description": "Production webhook for payment events",
                "status": "active"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Webhook created successfully. Save the secret — it will not be shown again."
                    },
                    "data": {
                      "$ref": "#/components/schemas/WebhookCreated"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Webhook created successfully. Save the secret — it will not be shown again.",
                  "data": {
                    "id": "wh_dyS2ZVTj",
                    "url": "https://your-domain.com/webhooks/gigstack",
                    "events": [
                      "payment.created",
                      "payment.succeeded"
                    ],
                    "status": "active",
                    "description": "Production webhook for payment events",
                    "owner": "8UWdgXELUhf022vuoq249mtGytG2",
                    "created_at": 1709090576567,
                    "secret": "3f9a1c0e7b2d4f6a8c1e3b5d7f9a2c4e6b8d0f1a3c5e7b9d2f4a6c8e0b1d3f5a"
                  },
                  "timestamp": 1709090576600
                }
              }
            }
          },
          "400": {
            "description": "Invalid webhook data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "callbacks": {
          "webhookEvent": {
            "{$request.body#/url}": {
              "post": {
                "summary": "Event delivery (sent by gigstack to your URL)",
                "description": "gigstack sends a `POST` for each event to every **active** webhook subscribed to it.\nThe body formats are described in `WebhookEventPayload`.\n\n**Resource events** (`payment.*`, `invoice.*`, `receipt.*`, `customer.*`, `service.*`)\n- Body: `WebhookPayloadV1` or `WebhookPayloadV2`, depending on the webhook's payload version.\n- Headers: `Content-Type: application/json`, plus any custom headers configured on the\n  webhook in the gigstack dashboard (for example `Authorization`). These deliveries are\n  not signed.\n- Each attempt times out after 10 seconds.\n- `408`, `429`, `5xx`, timeouts and network errors are retried with exponential backoff,\n  up to 16 attempts in total. Any other `4xx` is final.\n- Webhooks are never disabled automatically because of failed deliveries.\n\n**`sat.invoice.synced`**\n- Body: `SatInvoiceSyncedWebhookEvent`.\n- Headers: `Content-Type: application/json`, `X-Gigstack-Event`, and `X-Gigstack-Signature`.\n  The signature is `sha256=` + hex HMAC-SHA256 of the raw body, keyed with the webhook's\n  `secret`. It is absent for webhooks created before signing existed.\n- One attempt with a 10-second timeout. It is never retried, and the response is ignored.\n\n**`invoice_batch.completed`**\n- Sent once when every accepted item of a `POST /invoices/income/batch` batch has a final\n  status. Body: `InvoiceBatchCompletedWebhookEvent`.\n- Headers, signature and delivery are the same as for `sat.invoice.synced`: signed, one\n  attempt, never retried. Poll `GET /invoices/income/batch/{id}` as a fallback.\n\nOrder across events is not guaranteed, and the same event can arrive more than once.\nDe-duplicate, and respond with a `2xx` quickly.\n",
                "parameters": [
                  {
                    "name": "X-Gigstack-Event",
                    "in": "header",
                    "required": false,
                    "description": "`sat.invoice.synced` and `invoice_batch.completed` deliveries only: the event type.",
                    "schema": {
                      "$ref": "#/components/schemas/WebhookEventType"
                    }
                  },
                  {
                    "name": "X-Gigstack-Signature",
                    "in": "header",
                    "required": false,
                    "description": "`sat.invoice.synced` and `invoice_batch.completed` deliveries only: `sha256=<hex HMAC-SHA256 of the raw body, keyed with the webhook secret>`",
                    "schema": {
                      "type": "string",
                      "pattern": "^sha256=[0-9a-f]{64}$"
                    }
                  }
                ],
                "requestBody": {
                  "required": true,
                  "content": {
                    "application/json": {
                      "schema": {
                        "$ref": "#/components/schemas/WebhookEventPayload"
                      },
                      "examples": {
                        "v1": {
                          "summary": "Resource event, v1 body",
                          "value": {
                            "event": "payment.succeeded",
                            "team": "team_1234567890",
                            "webhook": "wh_dyS2ZVTj",
                            "livemode": true,
                            "data": {
                              "id": "payment_1234567890",
                              "status": "succeeded"
                            }
                          }
                        },
                        "v2": {
                          "summary": "Resource event, v2 body",
                          "value": {
                            "id": "log_4GqT7mZx9LpR2vWc8NdK--wh_dyS2ZVTj",
                            "type": "payment.succeeded",
                            "created": 1767225600000,
                            "livemode": true,
                            "data": {
                              "object": {
                                "id": "payment_1234567890",
                                "status": "succeeded"
                              }
                            }
                          }
                        },
                        "satInvoiceSynced": {
                          "summary": "sat.invoice.synced",
                          "value": {
                            "id": "evt_4f1c9a7e2b3d5c6a",
                            "event": "sat.invoice.synced",
                            "created_at": 1767225600,
                            "data": {
                              "uuid": "9D9B0E5B-0341-4C2B-8F3A-6E1D2C4B5A70",
                              "direction": "received",
                              "resource_status": "ready",
                              "issuer": {
                                "rfc": "EKU9003173C9",
                                "name": "ESCUELA KEMPER URGATE"
                              },
                              "receiver": {
                                "rfc": "MEE200101ABC",
                                "name": "MI EMPRESA EJEMPLO"
                              },
                              "total": 1160,
                              "currency": "MXN",
                              "issue_date": "2026-01-15T10:30:00",
                              "invoice_type": "I",
                              "status": "Vigente",
                              "team": "team_1234567890",
                              "credit_charged": true
                            }
                          }
                        },
                        "invoiceBatchCompleted": {
                          "summary": "invoice_batch.completed",
                          "value": {
                            "id": "evt_9a2b7c4d1e6f3a8b",
                            "event": "invoice_batch.completed",
                            "created_at": 1790784000,
                            "data": {
                              "id": "ibatch_5d41402abc4b2a76b9719d911017c592",
                              "livemode": true,
                              "total": 250,
                              "accepted": 248,
                              "rejected": 2,
                              "counts": {
                                "queued": 0,
                                "stamped": 245,
                                "failed": 2,
                                "duplicate": 1,
                                "needs_review": 0
                              },
                              "result": "partially_completed"
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "responses": {
                  "200": {
                    "description": "Any `2xx` acknowledges the delivery.\n- For resource events, `408`, `429` and `5xx` trigger a retry, and any other `4xx` is final.\n- For `sat.invoice.synced` and `invoice_batch.completed` the response is ignored.\n"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "get": {
        "operationId": "getWebhooksById",
        "tags": [
          "Webhooks"
        ],
        "summary": "Get webhook",
        "description": "Retrieve details of a specific webhook by ID.\n\n**gigstack Connect:** Access other teams' webhooks using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Webhook ID",
            "schema": {
              "type": "string",
              "example": "wh_dyS2ZVTj"
            },
            "example": "webhook_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Webhook retrieved successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicWebhook"
                    },
                    "timestamp": {
                      "type": "number",
                      "example": 1709090576567
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Webhook retrieved successfully",
                  "data": {
                    "id": "wh_dyS2ZVTj",
                    "url": "https://your-domain.com/webhooks/gigstack",
                    "events": [
                      "payment.succeeded",
                      "sat.invoice.synced"
                    ],
                    "status": "active",
                    "description": "Production webhook",
                    "owner": "8UWdgXELUhf022vuoq249mtGytG2",
                    "created_at": 1709090576567
                  },
                  "timestamp": 1709090576567
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Webhook not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateWebhooksById",
        "tags": [
          "Webhooks"
        ],
        "summary": "Update webhook",
        "description": "Update an existing webhook's configuration. All fields are optional.\n\n**gigstack Connect:** Update webhooks for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Webhook ID",
            "schema": {
              "type": "string",
              "example": "wh_dyS2ZVTj"
            },
            "example": "webhook_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdateInput"
              },
              "example": {
                "status": "inactive",
                "description": "Temporarily disabled for maintenance"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Webhook updated successfully"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ApiPublicWebhook"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Webhook updated successfully",
                  "data": {
                    "id": "wh_dyS2ZVTj",
                    "url": "https://your-domain.com/webhooks/gigstack",
                    "events": [
                      "payment.succeeded",
                      "sat.invoice.synced"
                    ],
                    "status": "inactive",
                    "description": "Temporarily disabled for maintenance",
                    "owner": "8UWdgXELUhf022vuoq249mtGytG2",
                    "created_at": 1709090576567
                  },
                  "timestamp": 1709090600000
                }
              }
            }
          },
          "400": {
            "description": "Invalid webhook data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Webhook not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhooksById",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete webhook",
        "description": "Permanently delete a webhook endpoint.\n\n**gigstack Connect:** Delete webhooks for other teams using the `team` parameter.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Webhook ID",
            "schema": {
              "type": "string",
              "example": "wh_dyS2ZVTj"
            },
            "example": "webhook_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Webhook deleted successfully"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      }
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Webhook deleted successfully",
                  "data": {
                    "deleted": true
                  },
                  "timestamp": 1709090600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "Webhook not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      }
    },
    "/catalogs/product-keys": {
      "get": {
        "operationId": "getCatalogsProductKeys",
        "tags": [
          "Catalogs"
        ],
        "summary": "Search SAT product keys",
        "description": "Full-text search over the SAT `c_ClaveProdServ` catalog, the same catalog the dashboard\nsearches when you pick a default product key. Returns the codes you assign to an item's\n`product_key`.\n\n**Search Capabilities:**\n- Matches on code, description and SAT taxonomy (type, division, group)\n- Typo-tolerant fuzzy matching, ranked by relevance\n- Paginated results\n\n**Notes:**\n- The catalog is published by the SAT and is identical for every team, so results are not\n  affected by `livemode` and contain no team data. Authentication is still required.\n- Typesense must be configured for your team.\n- The `q` (or `query`) parameter is required.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/SearchQueryParam"
          },
          {
            "$ref": "#/components/parameters/SearchQueryBackwardCompatParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/SearchPageParam"
          },
          {
            "$ref": "#/components/parameters/FieldsParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Product keys searched successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data",
                    "found",
                    "page",
                    "per_page",
                    "success",
                    "timestamp"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Product keys searched successfully"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiPublicProductKey"
                      }
                    },
                    "found": {
                      "type": "integer",
                      "description": "Total number of results found",
                      "example": 15
                    },
                    "page": {
                      "type": "integer",
                      "description": "Current page number",
                      "example": 1
                    },
                    "per_page": {
                      "type": "integer",
                      "description": "Number of results per page",
                      "example": 10
                    },
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64",
                      "example": 1704067200000
                    }
                  }
                },
                "example": {
                  "message": "Product keys searched successfully",
                  "data": [
                    {
                      "code": "84111506",
                      "description": "Servicios de facturación"
                    }
                  ],
                  "found": 1,
                  "page": 1,
                  "per_page": 10,
                  "success": true,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "missing_query": {
                    "summary": "Missing query parameter",
                    "value": {
                      "error": {
                        "code": "missing_query",
                        "message": "Query parameter is required"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "missing_typesense_key": {
                    "summary": "Typesense not configured",
                    "value": {
                      "error": {
                        "code": "missing_typesense_key",
                        "message": "Typesense API key not configured for this team"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/catalogs/unit-keys": {
      "get": {
        "operationId": "getCatalogsUnitKeys",
        "tags": [
          "Catalogs"
        ],
        "summary": "Search SAT unit keys",
        "description": "Full-text search over the SAT `c_ClaveUnidad` catalog. Returns the codes you assign to an\nitem's `unit_key`, together with the name commonly stored as `unit_name`.\n\n**Search Capabilities:**\n- Matches on unit key and name\n- Typo-tolerant fuzzy matching, ranked by relevance\n- Paginated results\n\n**Notes:**\n- The catalog is published by the SAT and is identical for every team, so results are not\n  affected by `livemode` and contain no team data. Authentication is still required.\n- Typesense must be configured for your team.\n- The `q` (or `query`) parameter is required.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "$ref": "#/components/parameters/SearchQueryParam"
          },
          {
            "$ref": "#/components/parameters/SearchQueryBackwardCompatParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/SearchPageParam"
          },
          {
            "$ref": "#/components/parameters/FieldsParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Unit keys searched successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "message",
                    "data",
                    "found",
                    "page",
                    "per_page",
                    "success",
                    "timestamp"
                  ],
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Unit keys searched successfully"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiPublicUnitKey"
                      }
                    },
                    "found": {
                      "type": "integer",
                      "description": "Total number of results found",
                      "example": 4
                    },
                    "page": {
                      "type": "integer",
                      "description": "Current page number",
                      "example": 1
                    },
                    "per_page": {
                      "type": "integer",
                      "description": "Number of results per page",
                      "example": 10
                    },
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64",
                      "example": 1704067200000
                    }
                  }
                },
                "example": {
                  "message": "Unit keys searched successfully",
                  "data": [
                    {
                      "code": "E48",
                      "name": "Unidad de servicio"
                    }
                  ],
                  "found": 1,
                  "page": 1,
                  "per_page": 10,
                  "success": true,
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                },
                "examples": {
                  "missing_query": {
                    "summary": "Missing query parameter",
                    "value": {
                      "error": {
                        "code": "missing_query",
                        "message": "Query parameter is required"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  },
                  "missing_typesense_key": {
                    "summary": "Typesense not configured",
                    "value": {
                      "error": {
                        "code": "missing_typesense_key",
                        "message": "Typesense API key not configured for this team"
                      },
                      "success": false,
                      "timestamp": 1767225600000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/auth/signup": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Headless signup (API-only path)",
        "description": "Create a complete gigstack account end-to-end without the alphav2 web UI.\nDesigned for AI agents and partner integrations: a single call provisions\na Firebase Auth user, billing account, team, plan subscription, and returns\nlive + test API keys.\n\n**Auth:** This endpoint authenticates with `X-Internal-API-Key` (partner-issued),\nNOT a normal `Authorization: Bearer` API token. Bearer tokens are scoped to a\nteam — a brand-new caller has none yet.\n\n**Idempotency:** `Idempotency-Key` header (UUID v4) is required. Retries with\nthe same key return the cached response and never re-create resources.\n\n**Plan paths:**\n- `plan_id: \"free\"` — direct Firestore write, no Stripe, instant activation.\n- Any paid plan — uses `stripe.subscriptions.create` with the supplied\n  PaymentMethod token (off-session). No Checkout redirect. `billingAccount.haveAPIAccess`\n  is set synchronously so the API gate passes on the first call.\n\n**RFC and FIEL:** not required at signup. Defaults to RFC genérico\n(`XAXX010101000`). Customers can later upload their own via\n`POST /v2/teams/{team_id}/sat-connection`. Clients, payments, services,\nreceipts, and webhooks all work without FIEL.\n\n**API keys:** returned in the response body **once** — not retrievable later.\nThe caller must store them immediately.\n",
        "operationId": "signup",
        "security": [
          {
            "signupApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "X-Internal-API-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Internal provisioning key, constant-time validated. This is the credential the\n`signupApiKey` security scheme refers to; `X-Signup-Api-Key` is accepted as an\nalias when this header is absent. A `Bearer` token is **not** used here.\n"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID v4. Required so retries are safe."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "name",
                  "plan_id"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "example": "agent@example.com"
                  },
                  "name": {
                    "type": "string",
                    "example": "Agent Builder Inc",
                    "description": "Used for displayName + legal_name placeholder."
                  },
                  "rfc": {
                    "type": "string",
                    "example": "XAXX010101000",
                    "description": "Optional. Defaults to RFC genérico if omitted."
                  },
                  "country": {
                    "type": "string",
                    "example": "MEX",
                    "default": "MEX"
                  },
                  "plan_id": {
                    "type": "string",
                    "example": "agent-tier",
                    "description": "A plan id from the subscriptionPricing collection. Use \"free\" for the free tier or \"agent-tier\" for the API-only paid plan."
                  },
                  "billing_cycle": {
                    "type": "string",
                    "enum": [
                      "monthly",
                      "annual"
                    ],
                    "example": "monthly",
                    "description": "Ignored for free plans."
                  },
                  "stripe_payment_method": {
                    "type": "string",
                    "example": "pm_1Q...",
                    "description": "Required for paid plans only. Created client-side via Stripe.js."
                  },
                  "livemode": {
                    "type": "boolean",
                    "default": true
                  },
                  "partner_ref": {
                    "type": "string",
                    "example": "SANTIAGO-A7K9",
                    "description": "Optional partner referral code. Captured for future commission routing (not yet wired to Stripe Connect transfer_data)."
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "example": {
                      "source": "my-agent-cli"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user_id": {
                      "type": "string"
                    },
                    "team_id": {
                      "type": "string"
                    },
                    "billing_account_id": {
                      "type": "string"
                    },
                    "subscription": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "id": {
                          "type": "string",
                          "nullable": true
                        },
                        "status": {
                          "type": "string"
                        },
                        "current_period_end": {
                          "type": "number",
                          "nullable": true
                        }
                      }
                    },
                    "api_keys": {
                      "type": "object",
                      "properties": {
                        "live": {
                          "type": "string",
                          "description": "JWT bearer token for live mode. Shown once — store immediately."
                        },
                        "test": {
                          "type": "string",
                          "description": "JWT bearer token for test mode. Shown once — store immediately."
                        }
                      }
                    },
                    "next_steps": {
                      "type": "object",
                      "properties": {
                        "fiel_upload_url": {
                          "type": "string"
                        },
                        "manifest_sign_url": {
                          "type": "string"
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "user_id": "aJGZiWGWQGfZEZk9XbtShj3pxBx2",
                  "team_id": "team_xxx",
                  "billing_account_id": "ba_xxx",
                  "subscription": {
                    "id": "sub_1Q...",
                    "status": "active",
                    "current_period_end": 1740000000
                  },
                  "api_keys": {
                    "live": "eyJhbGciOi...",
                    "test": "eyJhbGciOi..."
                  },
                  "next_steps": {
                    "fiel_upload_url": "POST /v2/teams/{team_id}/sat-connection",
                    "manifest_sign_url": "POST /v2/teams/{team_id}/manifest/sign",
                    "note": "RFC and FIEL only required for CFDI invoicing. Clients, payments, services, receipts, and webhooks all work without them."
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error (missing field, invalid plan_id, malformed Idempotency-Key)"
          },
          "401": {
            "description": "Missing or invalid X-Internal-API-Key"
          },
          "402": {
            "description": "Stripe rejected the supplied payment method"
          },
          "409": {
            "description": "Email already registered. Direct the user to sign in instead."
          },
          "500": {
            "description": "Internal Server Error (includes a binnacle_id for support)"
          },
          "503": {
            "description": "Endpoint disabled because INTERNAL_SIGNUP_API_KEY is not configured on the function."
          }
        }
      }
    },
    "/auth/health": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Health check",
        "operationId": "authHealth",
        "description": "Liveness probe for the auth module. Unauthenticated — the whole auth router is mounted\nas a public endpoint, so no credential is required or inspected.\n",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "auth"
                }
              }
            }
          }
        }
      }
    },
    "/sat-lists": {
      "get": {
        "operationId": "listSatLists",
        "tags": [
          "SAT Lists"
        ],
        "summary": "List SAT lists and sync status",
        "description": "Returns every SAT list definition tracked by gigstack, together with the metadata from its most recent sync.\n\ngigstack mirrors the RFC lists the SAT publishes under **Artículo 69**, **Artículo 69-B** and **Artículo 69-B Bis**.\nThe lists are re-synced automatically every Sunday from the SAT's published CSVs.\n\nEach list carries an `is_risky` flag. Risky lists (for example `Cancelados`, `Definitivos 69-B`, `No localizados`,\n`CSD sin efectos`) are the ones that indicate a counterparty you should not invoice; the remaining lists are\ninformational only.\n\nThe `sync` object is `null` for a list that has never completed a sync.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "SAT lists retrieved successfully. `data` is an array of list definitions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data",
                    "timestamp"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SatListDefinition"
                      }
                    },
                    "message": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "key": "art_69b_definitivos",
                      "label": "Definitivos 69-B",
                      "source": "art_69b",
                      "is_risky": true,
                      "filename": "Definitivos.csv",
                      "sync": {
                        "last_sync_at": "2026-09-06T06:00:00.000Z",
                        "last_status": "ok",
                        "row_count": 12843,
                        "previous_row_count": 12790,
                        "net_new": 53,
                        "removed": 0,
                        "duration_ms": 48210
                      }
                    }
                  ],
                  "message": "SAT lists retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/sat-lists/check/{rfc}": {
      "get": {
        "operationId": "getSatListsCheckByRfc",
        "tags": [
          "SAT Lists"
        ],
        "summary": "Check an RFC against the SAT lists",
        "description": "Checks whether an RFC appears on any of the SAT lists gigstack tracks, and returns every matching entry.\n\nUse this before invoicing a counterparty: `is_risky` is `true` when the RFC appears on at least one list\nflagged as risky (`Cancelados`, `Definitivos 69-B`, `Presuntos 69-B`, `No localizados`, `CSD sin efectos`, …),\nand `risky_lists` names exactly which ones.\n\nAn RFC that appears on no list returns `200` with `found: false` — a clean RFC is not a `404`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "rfc",
            "in": "path",
            "required": true,
            "description": "The RFC to check. Case-insensitive; must be 10-13 characters.",
            "schema": {
              "type": "string",
              "minLength": 10,
              "maxLength": 13,
              "example": "XAXX010101000"
            },
            "example": "PEGJ800101ABC"
          },
          {
            "name": "risky_only",
            "in": "query",
            "required": false,
            "description": "When `true`, only entries from lists flagged as risky are returned.",
            "schema": {
              "type": "boolean",
              "example": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "RFC checked against the SAT lists",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/SatListRfcCheck"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "rfc": "EKU9003173C9",
                    "found": false,
                    "is_risky": false,
                    "risky_lists": [],
                    "entries": []
                  },
                  "message": "RFC EKU9003173C9 checked against SAT lists",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Invalid RFC (must be between 10 and 13 characters)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/sat-lists/32d/{rfc}": {
      "get": {
        "operationId": "getSatOpinion32dByRfc",
        "tags": [
          "SAT Lists"
        ],
        "summary": "Consult the SAT \"Opinión del Cumplimiento\" (32-D) for an RFC",
        "description": "Consults the SAT's public *Opinión del Cumplimiento de Obligaciones Fiscales* (Artículo 32-D) service\nfor an RFC and, when the SAT publishes one, returns a link to the constancia PDF.\n\n### How to read the result — please read before building on this\n\nThe SAT's public service **only ever publishes positive opinions**, and only for taxpayers who\nexplicitly authorized public disclosure of their opinion. There are exactly two outcomes:\n\n- `status: \"positiva\"` (`found: true`) — the SAT publishes a positive opinion for this RFC, and\n  `pdf_url` links to the constancia.\n- `status: \"no_autorizado\"` (`found: false`) — the SAT publishes nothing for this RFC. **This means\n  the result is unknown.** Either the taxpayer never opted in to public disclosure, or no opinion is\n  published. It is **not** a negative opinion, it is **not** evidence of non-compliance, and it must\n  never be shown to a user as \"opinión negativa\", \"incumplido\", or anything equivalent. The only\n  correct reading is \"the SAT does not publish an opinion for this RFC\".\n\nThere is no third status: the SAT never exposes negative opinions through this service, so this\nendpoint can never tell you that a taxpayer is non-compliant.\n\nA failure reaching the SAT — network error, or the SAT changing its page — returns `500`. It is never\ncollapsed into `no_autorizado`, so `no_autorizado` always reflects a real answer from the SAT.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "rfc",
            "in": "path",
            "required": true,
            "description": "The RFC to consult. Case-insensitive; must be 10-13 characters.",
            "schema": {
              "type": "string",
              "minLength": 10,
              "maxLength": 13,
              "example": "EKU9003173C9"
            },
            "example": "EKU9003173C9"
          }
        ],
        "responses": {
          "200": {
            "description": "The SAT was consulted successfully (for both `positiva` and `no_autorizado`)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/SatOpinion32dCheck"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "rfc": "EKU9003173C9",
                    "status": "no_autorizado",
                    "found": false,
                    "pdf_url": null,
                    "checked_at": 1767225600000
                  },
                  "message": "SAT publishes no 32-D opinion for RFC EKU9003173C9 — the result is unknown, not negative",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Invalid RFC (must be between 10 and 13 characters)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "description": "The SAT could not be reached or its response could not be parsed. The taxpayer's status is\nunknown — do not interpret this as `no_autorizado` or as a negative opinion.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        }
      }
    },
    "/catalogs/health": {
      "get": {
        "tags": [
          "Catalogs"
        ],
        "summary": "Health check",
        "operationId": "catalogsHealth",
        "description": "Liveness probe for the catalogs module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "catalogs"
                }
              }
            }
          }
        }
      }
    },
    "/clients/health": {
      "get": {
        "tags": [
          "Clients"
        ],
        "summary": "Health check",
        "operationId": "clientsHealth",
        "description": "Liveness probe for the clients module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "clients"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/health": {
      "get": {
        "tags": [
          "Invoices"
        ],
        "summary": "Health check",
        "operationId": "invoicesHealth",
        "description": "Liveness probe for the invoices module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "invoices"
                }
              }
            }
          }
        }
      }
    },
    "/payments/health": {
      "get": {
        "tags": [
          "Payments"
        ],
        "summary": "Health check",
        "operationId": "paymentsHealth",
        "description": "Liveness probe for the payments module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "payments"
                }
              }
            }
          }
        }
      }
    },
    "/receipts/health": {
      "get": {
        "tags": [
          "Receipts"
        ],
        "summary": "Health check",
        "operationId": "receiptsHealth",
        "description": "Liveness probe for the receipts module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "receipts"
                }
              }
            }
          }
        }
      }
    },
    "/services/health": {
      "get": {
        "tags": [
          "Services"
        ],
        "summary": "Health check",
        "operationId": "servicesHealth",
        "description": "Liveness probe for the services module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "services"
                }
              }
            }
          }
        }
      }
    },
    "/teams/health": {
      "get": {
        "tags": [
          "Teams"
        ],
        "summary": "Health check",
        "operationId": "teamsHealth",
        "description": "Liveness probe for the teams module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "teams"
                }
              }
            }
          }
        }
      }
    },
    "/users/health": {
      "get": {
        "tags": [
          "Users"
        ],
        "summary": "Health check",
        "operationId": "usersHealth",
        "description": "Liveness probe for the users module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "users"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/health": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Health check",
        "operationId": "webhooksHealth",
        "description": "Liveness probe for the webhooks module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "webhooks"
                }
              }
            }
          }
        }
      }
    },
    "/documents": {
      "get": {
        "tags": [
          "Documents"
        ],
        "summary": "List documents",
        "operationId": "listDocuments",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nList the team's documents, newest first. Soft-deleted documents are excluded.\n\n`entity_type` and `entity_id` filter on the document's links. `entity_id` is applied\nclient-side after the query, so it only narrows the page that was already fetched —\ncombine it with a larger `limit` if you expect sparse matches.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size. Defaults to 50, capped at 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Id of the last document from the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "document_type",
            "in": "query",
            "required": false,
            "description": "Filter by document type.",
            "schema": {
              "$ref": "#/components/schemas/DocumentTypeEnum"
            }
          },
          {
            "name": "compliance_status",
            "in": "query",
            "required": false,
            "description": "Filter by compliance review state.",
            "schema": {
              "$ref": "#/components/schemas/DocumentComplianceStatusEnum"
            }
          },
          {
            "name": "entity_type",
            "in": "query",
            "required": false,
            "description": "Filter to documents linked to this kind of entity.",
            "schema": {
              "$ref": "#/components/schemas/DocumentLinkEntityTypeEnum"
            }
          },
          {
            "name": "entity_id",
            "in": "query",
            "required": false,
            "description": "Filter to documents linked to this specific entity id. Applied after the query.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Documents retrieved. Note the nested shape: the array lives at `data.data`, with\npagination alongside it inside `data`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "required": [
                            "data",
                            "has_more"
                          ],
                          "properties": {
                            "data": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/ApiPublicDocument"
                              }
                            },
                            "has_more": {
                              "type": "boolean",
                              "example": false
                            },
                            "next_cursor": {
                              "type": "string",
                              "nullable": true,
                              "description": "Pass back as `cursor` to fetch the next page. `null` on the last page.",
                              "example": "doc_1234567890"
                            }
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "data": [
                      {
                        "id": "doc_1234567890",
                        "document_type": "contract",
                        "name": "Contrato de servicios 2026 — Cliente ACME",
                        "description": "Contrato marco de prestación de servicios",
                        "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_123%2Fdocuments%2Fcontrato-acme.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                        "file_name": "contrato-acme.pdf",
                        "file_size": 284913,
                        "mime_type": "application/pdf",
                        "linked_entities": [
                          {
                            "entity_type": "client",
                            "entity_id": "client_1234567890",
                            "linked_at": 1767225600000
                          }
                        ],
                        "compliance_status": "pending_review",
                        "compliance_notes": null,
                        "valid_from": 1767225600000,
                        "valid_until": 1798761600000,
                        "ai_extraction": null,
                        "tags": [
                          "contrato",
                          "acme"
                        ],
                        "metadata": null,
                        "created_at": 1767225600000,
                        "created_by": "user_1234567890",
                        "updated_at": null,
                        "livemode": true
                      }
                    ],
                    "has_more": false,
                    "next_cursor": null
                  },
                  "message": "Documents retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "description": "`An error occurred while listing documents`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      },
      "post": {
        "tags": [
          "Documents"
        ],
        "summary": "Create document",
        "operationId": "createDocument",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nRegister a document that has already been uploaded to storage. This endpoint records\nmetadata — it does not accept the file itself; upload first and pass `fileUrl` and\n`storagePath`.\n\n`complianceStatus` is always set server-side to `pending_review` on create and cannot\nbe supplied here; change it later with `PATCH /v2/documents/{id}`.\n\nUnknown top-level keys are rejected (`400 validation_failed`).\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentInput"
              },
              "example": {
                "documentType": "contract",
                "name": "Contrato de servicios 2026 — Cliente ACME",
                "description": "Contrato marco de prestación de servicios",
                "fileUrl": "https://storage.googleapis.com/gigstack-docs/team_123/contrato-acme.pdf",
                "storagePath": "teams/team_123/documents/contrato-acme.pdf",
                "fileName": "contrato-acme.pdf",
                "fileSize": 284913,
                "mimeType": "application/pdf",
                "validFrom": 1767225600000,
                "validUntil": 1798761600000,
                "tags": [
                  "contrato",
                  "acme"
                ],
                "linkedEntities": [
                  {
                    "entityType": "client",
                    "entityId": "client_1234567890"
                  }
                ],
                "analyzeWithAI": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document created.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicDocument"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "doc_1234567890",
                    "document_type": "contract",
                    "name": "Contrato de servicios 2026 — Cliente ACME",
                    "description": "Contrato marco de prestación de servicios",
                    "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_123%2Fdocuments%2Fcontrato-acme.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                    "file_name": "contrato-acme.pdf",
                    "file_size": 284913,
                    "mime_type": "application/pdf",
                    "linked_entities": [
                      {
                        "entity_type": "client",
                        "entity_id": "client_1234567890",
                        "linked_at": 1767225600000
                      }
                    ],
                    "compliance_status": "pending_review",
                    "compliance_notes": null,
                    "valid_from": 1767225600000,
                    "valid_until": 1798761600000,
                    "ai_extraction": null,
                    "tags": [
                      "contrato",
                      "acme"
                    ],
                    "metadata": null,
                    "created_at": 1767225600000,
                    "created_by": "user_1234567890",
                    "updated_at": null,
                    "livemode": true
                  },
                  "message": "Document created successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Body validation failure, including unknown keys.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "description": "`An error occurred while creating document`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/documents/{id}": {
      "get": {
        "tags": [
          "Documents"
        ],
        "summary": "Get document",
        "operationId": "getDocument",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nRetrieve one document. Documents belonging to another team, and soft-deleted\ndocuments, are reported as `404` rather than `403`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Document id.",
            "schema": {
              "type": "string"
            },
            "example": "doc_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Document retrieved.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicDocument"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "doc_1234567890",
                    "document_type": "contract",
                    "name": "Contrato de servicios 2026 — Cliente ACME",
                    "description": "Contrato marco de prestación de servicios",
                    "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_123%2Fdocuments%2Fcontrato-acme.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                    "file_name": "contrato-acme.pdf",
                    "file_size": 284913,
                    "mime_type": "application/pdf",
                    "linked_entities": [
                      {
                        "entity_type": "client",
                        "entity_id": "client_1234567890",
                        "linked_at": 1767225600000
                      }
                    ],
                    "compliance_status": "pending_review",
                    "compliance_notes": null,
                    "valid_from": 1767225600000,
                    "valid_until": 1798761600000,
                    "ai_extraction": null,
                    "tags": [
                      "contrato",
                      "acme"
                    ],
                    "metadata": null,
                    "created_at": 1767225600000,
                    "created_by": "user_1234567890",
                    "updated_at": null,
                    "livemode": true
                  },
                  "message": "Document retrieved successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "`Document not found` — missing, owned by another team, or soft-deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "`An error occurred while retrieving document`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      },
      "patch": {
        "tags": [
          "Documents"
        ],
        "summary": "Update document",
        "operationId": "updateDocument",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nUpdate a document's metadata and compliance review state. Only fields explicitly\npresent in the body are written; omitted fields are left untouched.\n\nThe file itself (`fileUrl`, `storagePath`, `fileName`, `documentType`) is immutable —\nthose keys are not part of the update schema and are rejected as unknown.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Document id.",
            "schema": {
              "type": "string"
            },
            "example": "doc_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentUpdateInput"
              },
              "example": {
                "complianceStatus": "valid",
                "complianceNotes": "Revisado por el área fiscal, cumple con el requisito de materialidad.",
                "tags": [
                  "contrato",
                  "acme",
                  "revisado"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document updated.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicDocument"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "doc_1234567890",
                    "document_type": "contract",
                    "name": "Contrato de servicios 2026 — Cliente ACME",
                    "description": "Contrato marco de prestación de servicios",
                    "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_123%2Fdocuments%2Fcontrato-acme.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                    "file_name": "contrato-acme.pdf",
                    "file_size": 284913,
                    "mime_type": "application/pdf",
                    "linked_entities": [
                      {
                        "entity_type": "client",
                        "entity_id": "client_1234567890",
                        "linked_at": 1767225600000
                      }
                    ],
                    "compliance_status": "valid",
                    "compliance_notes": "Revisado por el área fiscal, cumple con el requisito de materialidad.",
                    "valid_from": 1767225600000,
                    "valid_until": 1798761600000,
                    "ai_extraction": null,
                    "tags": [
                      "contrato",
                      "acme"
                    ],
                    "metadata": null,
                    "created_at": 1767225600000,
                    "created_by": "user_1234567890",
                    "updated_at": 1767312000000,
                    "livemode": true
                  },
                  "message": "Document updated successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Body validation failure, including unknown keys.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "`Document not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "`An error occurred while updating document`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      },
      "delete": {
        "tags": [
          "Documents"
        ],
        "summary": "Delete document",
        "operationId": "deleteDocument",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\n**Soft delete.** The document is flagged `deleted` (with `deletedAt`/`deletedBy`) rather\nthan removed, and its id is pulled from the `satDocuments` array of every entity it was\nlinked to. It stops appearing in list and get responses.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Document id.",
            "schema": {
              "type": "string"
            },
            "example": "doc_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Document deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "required": [
                            "id"
                          ],
                          "properties": {
                            "id": {
                              "type": "string",
                              "example": "doc_1234567890"
                            }
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "message": "Document deleted successfully",
                  "timestamp": 1767225600000,
                  "data": {
                    "id": "doc_1234567890"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "`Document not found` — including a document that was already deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "`An error occurred while deleting document`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/documents/{id}/analyze": {
      "post": {
        "tags": [
          "Documents"
        ],
        "summary": "Analyze document with AI",
        "operationId": "analyzeDocument",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nRun AI extraction over the document and store the result on it under `ai_extraction`.\n\nOnly PDFs and PNG/JPEG/WEBP images can be analyzed. For PDFs the text layer is\nextracted first — a scanned PDF with no selectable text is rejected with `400`.\n\nThe request body is ignored; the prompt is derived from the document's `documentType`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Document id.",
            "schema": {
              "type": "string"
            },
            "example": "doc_1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Document analyzed. The returned document carries the new `ai_extraction`.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicDocument"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "doc_1234567890",
                    "document_type": "contract",
                    "name": "Contrato de servicios 2026 — Cliente ACME",
                    "description": "Contrato marco de prestación de servicios",
                    "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_123%2Fdocuments%2Fcontrato-acme.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                    "file_name": "contrato-acme.pdf",
                    "file_size": 284913,
                    "mime_type": "application/pdf",
                    "linked_entities": [
                      {
                        "entity_type": "client",
                        "entity_id": "client_1234567890",
                        "linked_at": 1767225600000
                      }
                    ],
                    "compliance_status": "pending_review",
                    "compliance_notes": null,
                    "valid_from": 1767225600000,
                    "valid_until": 1798761600000,
                    "ai_extraction": {
                      "summary": "Contrato de prestación de servicios de consultoría con vigencia de 12 meses.",
                      "parties": [
                        "MI EMPRESA EJEMPLO SA DE CV",
                        "ESCUELA KEMPER URGATE"
                      ]
                    },
                    "tags": [
                      "contrato",
                      "acme"
                    ],
                    "metadata": null,
                    "created_at": 1767225600000,
                    "created_by": "user_1234567890",
                    "updated_at": 1767225660000,
                    "livemode": true
                  },
                  "message": "Document analyzed successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "`error.code: invalid_request_body`. Messages:\n`Only PDF and image files (PNG, JPG, WEBP) can be analyzed`,\n`Failed to download file from storage`,\n`Failed to read PDF content. The file may be damaged or protected.`,\n`PDF does not contain enough text to analyze. It may be a scanned document.`\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "`Document not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "`Failed to process document analysis results` when the model output could not be\nparsed as JSON, or `An error occurred while analyzing document`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/documents/{id}/link": {
      "post": {
        "tags": [
          "Documents"
        ],
        "summary": "Link document to an entity",
        "operationId": "linkDocument",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nAttach the document to an invoice, payment, receipt or client. The link is appended to\nthe document's `linkedEntities` and the document id is added to the entity's\n`satDocuments` array.\n\nLinking the same document to the same entity twice returns `400`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Document id.",
            "schema": {
              "type": "string"
            },
            "example": "doc_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentLinkInput"
              },
              "example": {
                "entityType": "invoice",
                "entityId": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document linked. Returns the updated document.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicDocument"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "doc_1234567890",
                    "document_type": "contract",
                    "name": "Contrato de servicios 2026 — Cliente ACME",
                    "description": "Contrato marco de prestación de servicios",
                    "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_123%2Fdocuments%2Fcontrato-acme.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                    "file_name": "contrato-acme.pdf",
                    "file_size": 284913,
                    "mime_type": "application/pdf",
                    "linked_entities": [
                      {
                        "entity_type": "client",
                        "entity_id": "client_1234567890",
                        "linked_at": 1767225600000
                      },
                      {
                        "entity_type": "invoice",
                        "entity_id": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB",
                        "linked_at": 1767225660000
                      }
                    ],
                    "compliance_status": "pending_review",
                    "compliance_notes": null,
                    "valid_from": 1767225600000,
                    "valid_until": 1798761600000,
                    "ai_extraction": null,
                    "tags": [
                      "contrato",
                      "acme"
                    ],
                    "metadata": null,
                    "created_at": 1767225600000,
                    "created_by": "user_1234567890",
                    "updated_at": null,
                    "livemode": true
                  },
                  "message": "Document linked successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Body validation failure, or `Document is already linked to this entity`\n(`error.code: invalid_request_body`).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "`Document not found`, or `<entityType> not found` when the target entity does not\nexist or belongs to another team.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "`An error occurred while linking document`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      },
      "delete": {
        "tags": [
          "Documents"
        ],
        "summary": "Unlink document from an entity",
        "operationId": "unlinkDocument",
        "description": "**Availability:** This operation has no configured public API gateway route and is not available through the documented base URL.\n\nRemove the link between the document and an entity. The document itself is not deleted.\n\nThis `DELETE` takes a **request body** identifying the entity — the same shape as the\nlink call.\n\nIf the entity no longer exists, the link is still removed from the document and the call\nsucceeds.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Document id.",
            "schema": {
              "type": "string"
            },
            "example": "doc_1234567890"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentLinkInput"
              },
              "example": {
                "entityType": "invoice",
                "entityId": "B0C3E4F2-1A2B-4C5D-9E8F-0123456789AB"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document unlinked. Returns the updated document.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicDocument"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "doc_1234567890",
                    "document_type": "contract",
                    "name": "Contrato de servicios 2026 — Cliente ACME",
                    "description": "Contrato marco de prestación de servicios",
                    "file_url": "https://firebasestorage.googleapis.com/v0/b/gigstackpro.appspot.com/o/teams%2Fteam_123%2Fdocuments%2Fcontrato-acme.pdf?alt=media&token=9f1c7d84-3b2e-4a56-8c0d-1e7f5b9a2c43",
                    "file_name": "contrato-acme.pdf",
                    "file_size": 284913,
                    "mime_type": "application/pdf",
                    "linked_entities": [
                      {
                        "entity_type": "client",
                        "entity_id": "client_1234567890",
                        "linked_at": 1767225600000
                      }
                    ],
                    "compliance_status": "pending_review",
                    "compliance_notes": null,
                    "valid_from": 1767225600000,
                    "valid_until": 1798761600000,
                    "ai_extraction": null,
                    "tags": [
                      "contrato",
                      "acme"
                    ],
                    "metadata": null,
                    "created_at": 1767225600000,
                    "created_by": "user_1234567890",
                    "updated_at": null,
                    "livemode": true
                  },
                  "message": "Document unlinked successfully",
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "400": {
            "description": "Body validation failure, or `Document is not linked to this entity`\n(`error.code: invalid_request_body`).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "`Document not found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                }
              }
            }
          },
          "500": {
            "description": "`An error occurred while unlinking document`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternalServerError"
                }
              }
            }
          }
        },
        "x-gigstack-publicly-routed": false
      }
    },
    "/invoices/eom/run": {
      "post": {
        "tags": [
          "Invoices"
        ],
        "summary": "Trigger end-of-month global invoicing",
        "operationId": "runEndOfMonthInvoicing",
        "description": "Manually trigger the end-of-month (EOM) global invoicing process for your team, which\ngroups pending receipts into global invoices.\n\n**Two hard preconditions:**\n- The API key must be **livemode**. Test keys are rejected with `403`.\n- The call must happen on the **last calendar day of the month** (America/Mexico_City).\n  Any other day is rejected with `400`.\n- The call must happen **before 23:00 America/Mexico_City**. From 23:00 on, the automatic\n  end-of-month run takes over and manual calls are rejected with `400`.\n\nThe request body is ignored.\n\nThe response is returned as soon as the process is *triggered* — it does not wait for\nthe run to finish. A validation pass runs asynchronously afterwards; failures there are\nlogged server-side and are not reflected in this response.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "EOM process triggered.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "global_invoice_time": {
                              "type": "string",
                              "description": "Trigger time, formatted `dd/MM/yyyy HH:mm:ss` in America/Mexico_City.",
                              "example": "31/01/2026 23:59:00"
                            }
                          }
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "message": "The end-of-month global invoicing process has been triggered successfully.",
                  "timestamp": 1767225600000,
                  "data": {
                    "global_invoice_time": "31/01/2026 23:59:00"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`error.code: operation_not_allowed` — `This endpoint is only available on the last\nday of each month.` (`error.details` names today's date and the next eligible date),\nor `Manual end-of-month runs are not available from 23:00 (America/Mexico_City) on\nthe last day of the month.`\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "operation_not_allowed",
                    "message": "This endpoint is only available on the last day of each month.",
                    "details": "Today is 15/01/2026. The next eligible date is 31/01/2026."
                  },
                  "timestamp": 1767225600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`error.code: operation_not_allowed` — `This endpoint is only available with\nlivemode API keys.`\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "description": "`error.code: external_service_error` — the downstream EOM execution function\nreturned an error. `error.details` carries the upstream text. Nothing was invoiced.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "external_service_error",
                    "message": "The EOM execution function returned an error. Please try again.",
                    "details": "upstream returned 500"
                  },
                  "timestamp": 1767225600000
                }
              }
            }
          }
        }
      }
    },
    "/invoices/download/pfx": {
      "post": {
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Connect FIEL credentials from a PFX file",
        "operationId": "connectFielPfx",
        "description": "Register the team's FIEL (e.firma) with the bulk-download service by uploading a\nPKCS#12 / PFX bundle and its password.\n\n> ### ⚠️ Sensitive credentials\n> `pfx` and `pfx_password` are **live security credentials** — the PFX embeds the FIEL\n> private key, and the password unlocks it. Together they can impersonate the taxpayer\n> before the SAT.\n>\n> - Send them only over TLS, only to this endpoint.\n> - Never log them, never put them in a URL, never commit them, never paste them into a\n>   shared document or ticket.\n> - The example values below are **placeholders**, not usable credentials. Do not treat\n>   any example in this document as a real secret to copy.\n>\n> The server encrypts both values at rest and never returns them in any response.\n\nThe certificate is validated before anything is stored: it must parse with the supplied\npassword, must not be expired, and its RFC must match the team's configured RFC. Each\nRFC needs its own team.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "pfx",
                  "pfx_password"
                ],
                "properties": {
                  "pfx": {
                    "type": "string",
                    "writeOnly": true,
                    "description": "**Sensitive.** Base64-encoded PFX/PKCS#12 file containing the FIEL\ncertificate and private key. Never logged or echoed back.\n",
                    "example": "<BASE64_PFX_PLACEHOLDER>"
                  },
                  "pfx_password": {
                    "type": "string",
                    "format": "password",
                    "writeOnly": true,
                    "description": "**Sensitive.** Password protecting the PFX file. Never logged or\nechoed back.\n",
                    "example": "<PFX_PASSWORD_PLACEHOLDER>"
                  }
                }
              },
              "example": {
                "pfx": "<BASE64_PFX_PLACEHOLDER>",
                "pfx_password": "<PFX_PASSWORD_PLACEHOLDER>"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "FIEL connected. The response describes the certificate but never echoes the PFX\nor its password.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "message",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "message": {
                      "type": "string",
                      "example": "FIEL credentials connected successfully"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rfc": {
                          "type": "string",
                          "example": "MEE200101ABC"
                        },
                        "expires_at": {
                          "type": "integer",
                          "format": "int64",
                          "description": "Certificate expiry, epoch milliseconds.",
                          "example": 1893456000000
                        },
                        "expires_at_readable": {
                          "type": "string",
                          "example": "31/12/2029"
                        },
                        "serial_number": {
                          "type": "string",
                          "example": "00001000000512345678"
                        },
                        "sync_start_date": {
                          "type": "string",
                          "description": "Earliest date Prodigia will sync invoices from.",
                          "example": "2023-08-05"
                        },
                        "registered": {
                          "type": "boolean",
                          "example": true
                        },
                        "registered_at": {
                          "type": "integer",
                          "format": "int64",
                          "example": 1767225600000
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "FIEL credentials connected successfully",
                  "data": {
                    "rfc": "MEE200101ABC",
                    "expires_at": 1893456000000,
                    "expires_at_readable": "31/12/2029",
                    "serial_number": "00001000000512345678",
                    "sync_start_date": "2023-08-05",
                    "registered": true,
                    "registered_at": 1767225600000
                  }
                }
              }
            }
          },
          "400": {
            "description": "Rejected before anything is stored. `message` is one of: `Team not found`,\n`Team RFC not configured`, `Missing PFX`, `Missing PFX password`,\n`Invalid PFX file or password`, `Could not extract RFC from certificate`,\n`RFC mismatch`, `Certificate expired`.\n\n`Invalid PFX file or password` does not distinguish between a corrupt bundle and\na wrong password — by design.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "message": "RFC mismatch",
                  "error": "FIEL certificate RFC (AAA010101AAA) does not match your team RFC (MEE200101ABC). Each RFC requires its own team."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "description": "`An error occurred while connecting FIEL credentials`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/invoices/download/sync-period": {
      "put": {
        "tags": [
          "Descarga Masiva SAT"
        ],
        "summary": "Update bulk-download sync period",
        "operationId": "updateBulkDownloadSyncPeriod",
        "description": "Re-register the team with the bulk-download provider so it syncs invoices from the\nearliest date the service allows.\n\n**The request body is ignored.** `sync_start_date` is always computed server-side and is\nnever accepted as user input — you cannot ask for an arbitrary start date.\n\nRequires a team RFC, a prior FIEL registration, stored FIEL credentials, and a phone\nnumber on the stored FIEL record.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TeamParameter"
          }
        ],
        "responses": {
          "200": {
            "description": "Sync period updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "message",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "message": {
                      "type": "string",
                      "example": "Sync period updated. Prodigia will now sync invoices from 2023-08-05."
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rfc": {
                          "type": "string",
                          "example": "MEE200101ABC"
                        },
                        "sync_start_date": {
                          "type": "string",
                          "example": "2023-08-05"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "Sync period updated. Prodigia will now sync invoices from 2023-08-05.",
                  "data": {
                    "rfc": "MEE200101ABC",
                    "sync_start_date": "2023-08-05"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A precondition failed. `message` is one of: `Team RFC not configured`,\n`Team not registered for bulk downloads. Complete FIEL upload first.`,\n`No stored FIEL credentials found. Upload your FIEL first.`,\n`Phone number required. Re-upload your FIEL with a phone number.`,\n`Failed to update sync period` (with the provider's reason in `error`).\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": false,
                  "message": "Team not registered for bulk downloads. Complete FIEL upload first."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "500": {
            "description": "`Error updating sync period`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/platform-payouts": {
      "post": {
        "operationId": "createPlatformPayoutRun",
        "tags": [
          "Platform Payouts"
        ],
        "summary": "Upload files and plan a platform payouts run",
        "description": "Uploads the **movements** and **commissions** files and computes the plan: which CFDIs will be\nissued for each provider, and why any row is excluded. Nothing is stamped here; review the plan with\n`GET /platform-payouts/{id}` and `GET /platform-payouts/{id}/movements`, then call\n`POST /platform-payouts/{id}/confirm`.\n\n**Who can call it.** The credential's team must be a marketplace **master team** whose billing\naccount has platform payouts enabled. API keys and OAuth tokens act as the team; user-scoped\ntokens (MCP, dashboard) must belong to the team and hold `editor` permission on invoices.\nSending gigstack Connect's `team` parameter moves the request to a connected team, which is not a\nmaster team, so it is refused with `not_master_team`. These checks (`403` `not_master_team`,\n`no_billing_account`, `feature_disabled`, `team_not_found`, `not_a_member`) run right after the\n`Idempotency-Key` check and **before the upload is read**: a refused request's files are never\nprocessed or stored.\n\n**Planning is synchronous.** The response carries the run with status `plan_ready`, or\n`plan_failed` with a Spanish `error` (unreadable file, missing columns, empty file, too many rows).\nRow-level problems do not fail the plan: the row becomes an excluded movement with a reason.\n\n**Idempotent on `Idempotency-Key` (required).** The run id is derived from your team, the key's\nmode and the header value, and the run records a fingerprint of the two files' **contents** (their\nbytes; file names don't count). The first request creates the run (`201`). A later request with the\nsame key and the same files returns that same run (`200`), whatever its status, without planning\nagain. The same key with **different** files is refused with `409 idempotency_key_reused`. Runs\ncreated before the fingerprint existed have none and are returned as before (`200`) whatever files\nyou send. A retry that arrives while the first request is still planning gets the run in\n`planning`: poll `GET /platform-payouts/{id}`. A failed plan stays failed under its key: fix the\nfile and send a **new** key.\n\n**Tax policy.** Which documents each provider gets, and their SAT keys and withholding rates,\ncome from your master account's policy, set at onboarding (defaults: ground passenger transport,\nrégimen `625`, CSD required, service type `01`, 2.1% ISR). Contact support to configure it.\n\n**Mode.** `livemode` comes only from the credential: a test key creates a test run.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Your identifier for this upload, 8-128 characters of `A-Z a-z 0-9 . _ : -`. Checked before the\nfiles are read. Reusing it with the same files returns the run it first created; reusing it with\ndifferent files is `409 idempotency_key_reused`.\n",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]{8,128}$"
            },
            "example": "payouts-2026-08-v1"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PlatformPayoutRunCreateInput"
              },
              "encoding": {
                "movements_file": {
                  "contentType": "text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, application/octet-stream"
                },
                "commissions_file": {
                  "contentType": "text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, application/octet-stream"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Retry of an earlier request with the same `Idempotency-Key` and the same file contents (or a\nrun created before file fingerprints existed): the run it created, in whatever status it is\nnow. Nothing is planned again. `planning` means the first request is still working; poll\n`GET /platform-payouts/{id}`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicPlatformPayoutRun"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c",
                    "status": "planning",
                    "result": null,
                    "livemode": true,
                    "team": "team_1234567890",
                    "created_at": 1788220800000,
                    "plan_ready_at": null,
                    "confirmed_at": null,
                    "completed_at": null,
                    "files": {
                      "movements": "movimientos-agosto-2026.csv",
                      "commissions": "comisiones-agosto-2026.xlsx"
                    },
                    "months": [],
                    "total_movements": 0,
                    "included_count": 0,
                    "excluded_count": 0,
                    "planned_documents": {
                      "income": 0,
                      "certificate": 0,
                      "commission": 0
                    },
                    "exclusion_summary": {},
                    "exclusion_code_summary": {},
                    "progress": {
                      "stamped_count": 0,
                      "failed_count": 0,
                      "income_invoices_count": 0,
                      "certificates_count": 0,
                      "commission_invoices_count": 0,
                      "commission_failed_count": 0,
                      "income_invoices_amount": 0
                    },
                    "error": null
                  },
                  "timestamp": 1788220802000
                }
              }
            }
          },
          "201": {
            "description": "Run created and planned. `data.status` is `plan_ready` or `plan_failed` (with `data.error`).\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicPlatformPayoutRun"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "plan_ready": {
                    "summary": "Plan computed",
                    "value": {
                      "success": true,
                      "data": {
                        "id": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c",
                        "status": "plan_ready",
                        "result": null,
                        "livemode": true,
                        "team": "team_1234567890",
                        "created_at": 1788220800000,
                        "plan_ready_at": 1788220804120,
                        "confirmed_at": null,
                        "completed_at": null,
                        "files": {
                          "movements": "movimientos-agosto-2026.csv",
                          "commissions": "comisiones-agosto-2026.xlsx"
                        },
                        "months": [
                          "2026-08"
                        ],
                        "total_movements": 412,
                        "included_count": 398,
                        "excluded_count": 14,
                        "planned_documents": {
                          "income": 398,
                          "certificate": 398,
                          "commission": 57
                        },
                        "exclusion_summary": {
                          "Sin sellos (CSD) en Gigstack": 9,
                          "El proveedor no tiene cuenta en Gigstack": 5
                        },
                        "exclusion_code_summary": {
                          "missing_csd": 9,
                          "provider_not_found": 5
                        },
                        "progress": {
                          "stamped_count": 0,
                          "failed_count": 0,
                          "income_invoices_count": 0,
                          "certificates_count": 0,
                          "commission_invoices_count": 0,
                          "commission_failed_count": 0,
                          "income_invoices_amount": 0
                        },
                        "error": null
                      },
                      "timestamp": 1788220804180
                    }
                  },
                  "plan_failed": {
                    "summary": "Plan failed on the file (use a new Idempotency-Key after fixing it)",
                    "value": {
                      "success": true,
                      "data": {
                        "id": "batchrun_9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e",
                        "status": "plan_failed",
                        "result": null,
                        "livemode": true,
                        "team": "team_1234567890",
                        "created_at": 1788220800000,
                        "plan_ready_at": 1788220801020,
                        "confirmed_at": null,
                        "completed_at": null,
                        "files": {
                          "movements": "movimientos-agosto-2026.csv",
                          "commissions": "comisiones-agosto-2026.xlsx"
                        },
                        "months": [],
                        "total_movements": 0,
                        "included_count": 0,
                        "excluded_count": 0,
                        "planned_documents": {
                          "income": 0,
                          "certificate": 0,
                          "commission": 0
                        },
                        "exclusion_summary": {},
                        "exclusion_code_summary": {},
                        "progress": {
                          "stamped_count": 0,
                          "failed_count": 0,
                          "income_invoices_count": 0,
                          "certificates_count": 0,
                          "commission_invoices_count": 0,
                          "commission_failed_count": 0,
                          "income_invoices_amount": 0
                        },
                        "error": "Al archivo de movimientos le faltan estas columnas: Fecha del movimiento, Subtotal."
                      },
                      "timestamp": 1788220801070
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request was refused before any run was created. `error.code`:\n\n- `invalid_request_body` - `Idempotency-Key` missing or malformed.\n- `invalid_content_type` - the body is not `multipart/form-data`.\n- `file_required` - `movements_file` or `commissions_file` is missing (`details` names it).\n- `empty_file` - a file has zero bytes.\n- `invalid_file_format` - the extension is not `.csv`, `.txt`, `.xlsx`, `.xls` or `.xlsm`.\n- `unexpected_file` - a file part other than the two above, one of them sent twice, or more than two files.\n- `too_many_fields` - more than 10 plain form fields.\n- `file_upload_error` - the multipart body could not be parsed.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "examples": {
                  "missing_idempotency_key": {
                    "summary": "Idempotency-Key header missing",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Idempotency-Key header is required"
                      },
                      "timestamp": 1788220800000
                    }
                  },
                  "malformed_idempotency_key": {
                    "summary": "Idempotency-Key does not match the format",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_request_body",
                        "message": "Idempotency-Key must be 8-128 chars matching [A-Za-z0-9._:-]"
                      },
                      "timestamp": 1788220800000
                    }
                  },
                  "file_required": {
                    "summary": "A file is missing",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "file_required",
                        "message": "File is required",
                        "details": "Field 'commissions_file' must contain a file"
                      },
                      "timestamp": 1788220800000
                    }
                  },
                  "invalid_file_format": {
                    "summary": "Unsupported extension",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_file_format",
                        "message": "Invalid file extension. Allowed extensions: .csv, .txt, .xlsx, .xls, .xlsm"
                      },
                      "timestamp": 1788220800000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Either the authentication layer refused the credential (raw body, see `AuthForbidden`), or\nthe team may not use platform payouts (standardized envelope). The team checks run before the\nupload is read, so the files are not processed. `error.code`:\n\n- `not_master_team` - the team is not a marketplace master team (also the answer when the\n  gigstack Connect `team` parameter points at a connected team).\n- `no_billing_account` - the team has no billing account.\n- `feature_disabled` - platform payouts is not enabled on the billing account. Contact support.\n- `team_not_found` - the team document does not exist.\n- `not_a_member` / `forbidden` - a user-scoped token whose user is not a member of the team,\n  or lacks `editor` permission on invoices (`This action requires editor access to invoices`).\n",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/StandardErrorResponse"
                    },
                    {
                      "$ref": "#/components/schemas/AuthMiddlewareError"
                    }
                  ]
                },
                "examples": {
                  "feature_disabled": {
                    "summary": "Platform payouts not enabled on the billing account",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "feature_disabled",
                        "message": "La facturación por archivo no está habilitada en esta cuenta. Contacta a soporte."
                      },
                      "timestamp": 1788220800000
                    }
                  },
                  "not_master_team": {
                    "summary": "Not a marketplace master team",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "not_master_team",
                        "message": "Esta cuenta no es una cuenta principal de marketplace."
                      },
                      "timestamp": 1788220800000
                    }
                  },
                  "missing_invoices_permission": {
                    "summary": "User-scoped token without editor permission on invoices",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "forbidden",
                        "message": "This action requires editor access to invoices"
                      },
                      "timestamp": 1788220800000
                    }
                  },
                  "revoked_api_key": {
                    "summary": "Authentication layer - API key revoked or disabled",
                    "value": {
                      "message": "API Key inválida.",
                      "details": "Invalid API Key"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The `Idempotency-Key` names a run this request can't be answered with. `error.code`:\n\n- `idempotency_key_reused` - the key was already used with **different file contents**\n  (compared by bytes, not names). The new files were not planned. Send them under a new\n  `Idempotency-Key`; to get the original run, use `GET /platform-payouts/{id}`.\n- `run_exists` - the derived run id is held by a run of another team. Not expected in\n  practice, since the id includes your team; send a different `Idempotency-Key`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "examples": {
                  "idempotency_key_reused": {
                    "summary": "Same Idempotency-Key, different files",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "idempotency_key_reused",
                        "message": "Esta Idempotency-Key ya se usó con otros archivos. Usa una nueva para subir archivos distintos."
                      },
                      "timestamp": 1788220800000
                    }
                  },
                  "run_exists": {
                    "summary": "Run id held by another team",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "run_exists",
                        "message": "Esta corrida ya existe."
                      },
                      "timestamp": 1788220800000
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "`file_too_large`: a file exceeds 5 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "file_too_large",
                    "message": "File size exceeds maximum allowed size of 5MB",
                    "details": "Field 'movements_file'"
                  },
                  "timestamp": 1788220800000
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (`internal_server_error`). Failures while planning are normally returned as\na `plan_failed` run instead; this status means the run could not be created or read at all.\nRetrying with the **same** `Idempotency-Key` is safe.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "internal_server_error",
                    "message": "No pudimos calcular el plan. Intenta de nuevo o contacta a soporte."
                  },
                  "timestamp": 1788220800000
                }
              }
            }
          }
        }
      }
    },
    "/platform-payouts/{id}": {
      "get": {
        "operationId": "getPlatformPayoutRun",
        "tags": [
          "Platform Payouts"
        ],
        "summary": "Get a platform payouts run",
        "description": "Returns the run: its status, plan totals and, once confirmed, the worker's progress. Poll it after\nconfirming until `status` is `completed` or `failed`; the worker runs every minute. Then read\n`result`, not `status`, to know how the run went: `status: completed` only means the worker has\nnothing left to try, while `result` tells `completed` (everything issued) from\n`partially_completed` (some documents failed) and `failed` (nothing issued).\n\nA run of another team, or of the other mode (a live run with a test key), answers `404`\n`run_not_found`, never `403`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Run id, as returned by `POST /platform-payouts`.",
            "schema": {
              "type": "string",
              "pattern": "^batchrun_[A-Za-z0-9]{6,40}$"
            },
            "example": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c"
          }
        ],
        "responses": {
          "200": {
            "description": "The run. Once it is finished, `result` says how it went: `completed`, `partially_completed`\nor `failed`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicPlatformPayoutRun"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "stamping": {
                    "summary": "Confirmed, worker in progress",
                    "value": {
                      "success": true,
                      "data": {
                        "id": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c",
                        "status": "stamping",
                        "result": null,
                        "livemode": true,
                        "team": "team_1234567890",
                        "created_at": 1788220800000,
                        "plan_ready_at": 1788220804120,
                        "confirmed_at": 1788221400000,
                        "completed_at": null,
                        "files": {
                          "movements": "movimientos-agosto-2026.csv",
                          "commissions": "comisiones-agosto-2026.xlsx"
                        },
                        "months": [
                          "2026-08"
                        ],
                        "total_movements": 412,
                        "included_count": 398,
                        "excluded_count": 14,
                        "planned_documents": {
                          "income": 398,
                          "certificate": 398,
                          "commission": 57
                        },
                        "exclusion_summary": {
                          "Sin sellos (CSD) en Gigstack": 9,
                          "El proveedor no tiene cuenta en Gigstack": 5
                        },
                        "exclusion_code_summary": {
                          "missing_csd": 9,
                          "provider_not_found": 5
                        },
                        "progress": {
                          "stamped_count": 120,
                          "failed_count": 2,
                          "income_invoices_count": 122,
                          "certificates_count": 120,
                          "commission_invoices_count": 0,
                          "commission_failed_count": 0,
                          "income_invoices_amount": 161497.5
                        },
                        "error": null
                      },
                      "timestamp": 1788221700000
                    }
                  },
                  "partially_completed": {
                    "summary": "Finished, some documents failed",
                    "value": {
                      "success": true,
                      "data": {
                        "id": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c",
                        "status": "completed",
                        "result": "partially_completed",
                        "livemode": true,
                        "team": "team_1234567890",
                        "created_at": 1788220800000,
                        "plan_ready_at": 1788220804120,
                        "confirmed_at": 1788221400000,
                        "completed_at": 1788224100000,
                        "files": {
                          "movements": "movimientos-agosto-2026.csv",
                          "commissions": "comisiones-agosto-2026.xlsx"
                        },
                        "months": [
                          "2026-08"
                        ],
                        "total_movements": 412,
                        "included_count": 398,
                        "excluded_count": 14,
                        "planned_documents": {
                          "income": 398,
                          "certificate": 398,
                          "commission": 57
                        },
                        "exclusion_summary": {
                          "Sin sellos (CSD) en Gigstack": 9,
                          "El proveedor no tiene cuenta en Gigstack": 5
                        },
                        "exclusion_code_summary": {
                          "missing_csd": 9,
                          "provider_not_found": 5
                        },
                        "progress": {
                          "stamped_count": 395,
                          "failed_count": 3,
                          "income_invoices_count": 397,
                          "certificates_count": 396,
                          "commission_invoices_count": 56,
                          "commission_failed_count": 1,
                          "income_invoices_amount": 525528.75
                        },
                        "error": null
                      },
                      "timestamp": 1788224160000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "No run with this id in your team and mode (`run_not_found`). A user-scoped token whose user is\nnot a member of the team gets `resource_not_found` (`Batch run not found`) instead.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "run_not_found",
                    "message": "No encontramos esta corrida."
                  },
                  "timestamp": 1788221700000
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/platform-payouts/{id}/movements": {
      "get": {
        "operationId": "listPlatformPayoutMovements",
        "tags": [
          "Platform Payouts"
        ],
        "summary": "List a platform payouts run's movements",
        "description": "One entry per row of the movements file, in file order, with the state of its income invoice and\nretention certificate. Use it to review exclusions before confirming, and to find failures after.\n\nCursor pagination: pass `data.next` back as `next` while `data.has_more` is `true`. The cursor is\nstable while the worker updates statuses, so pages never overlap or skip rows.\n\nCommission invoices (one per provider-month) are not listed here; the run only reports their counts.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Run id.",
            "schema": {
              "type": "string",
              "pattern": "^batchrun_[A-Za-z0-9]{6,40}$"
            },
            "example": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Movements per page (default **50**, 1-100).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "example": 50
          },
          {
            "name": "next",
            "in": "query",
            "required": false,
            "description": "Opaque cursor from the previous page's `data.next`. Omit for the first page.",
            "schema": {
              "type": "string"
            },
            "example": "51"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of movements. Note the nesting: the array is at `data.data`, the cursor at `data.next`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicPlatformPayoutMovementsPage"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "data": [
                      {
                        "id": "P10482_2026-08-04_125000_0",
                        "line": 2,
                        "status": "stamped",
                        "provider": {
                          "id": "P10482",
                          "name": "ESCUELA KEMPER URGATE",
                          "email": "proveedor@example.com",
                          "tax_id": "EKU9003173C9",
                          "team": "team_0987654321"
                        },
                        "movement_type": "Pago semanal",
                        "date": "2026-08-04",
                        "month": "2026-08",
                        "subtotal": 1250,
                        "commission": 96.15,
                        "exclusion_reason": null,
                        "exclusion_codes": [],
                        "error": null,
                        "income": {
                          "planned": true,
                          "status": "stamped",
                          "reason": null,
                          "reason_code": null,
                          "invoice_id": "7C2E4B1A-9D3F-4E8A-B6C5-1F2A3B4C5D6E",
                          "uuid": "7C2E4B1A-9D3F-4E8A-B6C5-1F2A3B4C5D6E",
                          "total": 1323.75,
                          "error": null,
                          "error_code": null
                        },
                        "certificate": {
                          "planned": true,
                          "status": "stamped",
                          "reason": null,
                          "reason_code": null,
                          "invoice_id": "0A1B2C3D-4E5F-4A6B-8C7D-9E0F1A2B3C4D",
                          "uuid": "0A1B2C3D-4E5F-4A6B-8C7D-9E0F1A2B3C4D",
                          "total": null,
                          "error": null,
                          "error_code": null
                        }
                      },
                      {
                        "id": "P20931_2026-08-04_98000_0",
                        "line": 3,
                        "status": "excluded",
                        "provider": {
                          "id": "P20931",
                          "name": "ESCUELA KEMPER URGATE",
                          "email": "otro.proveedor@example.com",
                          "tax_id": "EKU9003173C9",
                          "team": "team_1122334455"
                        },
                        "movement_type": "Pago semanal",
                        "date": "2026-08-04",
                        "month": "2026-08",
                        "subtotal": 980,
                        "commission": 75.38,
                        "exclusion_reason": "Sin sellos (CSD) en Gigstack",
                        "exclusion_codes": [
                          "missing_csd"
                        ],
                        "error": null,
                        "income": {
                          "planned": false,
                          "status": "skipped",
                          "reason": "Sin sellos (CSD) en Gigstack",
                          "reason_code": "missing_csd",
                          "invoice_id": null,
                          "uuid": null,
                          "total": null,
                          "error": null,
                          "error_code": null
                        },
                        "certificate": {
                          "planned": false,
                          "status": "skipped",
                          "reason": "Sin sellos (CSD) en Gigstack",
                          "reason_code": "missing_csd",
                          "invoice_id": null,
                          "uuid": null,
                          "total": null,
                          "error": null,
                          "error_code": null
                        }
                      },
                      {
                        "id": "P30577_2026-08-05_110000_0",
                        "line": 4,
                        "status": "failed",
                        "provider": {
                          "id": "P30577",
                          "name": "ESCUELA KEMPER URGATE",
                          "email": "tercer.proveedor@example.com",
                          "tax_id": "EKU9003173C9",
                          "team": "team_5566778899"
                        },
                        "movement_type": "Pago semanal",
                        "date": "2026-08-05",
                        "month": "2026-08",
                        "subtotal": 1100,
                        "commission": 84.62,
                        "exclusion_reason": null,
                        "exclusion_codes": [],
                        "error": "Timbrado interrumpido: verificar en el PAC antes de reintentar",
                        "income": {
                          "planned": false,
                          "status": "skipped",
                          "reason": "Sin serie de facturación configurada",
                          "reason_code": "missing_series",
                          "invoice_id": null,
                          "uuid": null,
                          "total": null,
                          "error": null,
                          "error_code": null
                        },
                        "certificate": {
                          "planned": true,
                          "status": "failed",
                          "reason": null,
                          "reason_code": null,
                          "invoice_id": null,
                          "uuid": null,
                          "total": null,
                          "error": "Timbrado interrumpido: verificar en el PAC antes de reintentar",
                          "error_code": "interrupted_stamp"
                        }
                      }
                    ],
                    "next": "4",
                    "has_more": true
                  },
                  "timestamp": 1788224160000
                }
              }
            }
          },
          "400": {
            "description": "`invalid_limit` - `limit` is not an integer between 1 and 100.\n`invalid_cursor` - `next` is not a cursor returned by this endpoint.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "examples": {
                  "invalid_limit": {
                    "summary": "limit out of range",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_limit",
                        "message": "limit must be an integer between 1 and 100"
                      },
                      "timestamp": 1788221700000
                    }
                  },
                  "invalid_cursor": {
                    "summary": "next is not a valid cursor",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "invalid_cursor",
                        "message": "next is not a valid cursor"
                      },
                      "timestamp": 1788221700000
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AuthForbidden"
          },
          "404": {
            "description": "No run with this id in your team and mode (`run_not_found`); `resource_not_found` for a\nuser-scoped token whose user is not a member of the team. Checked before `limit` and `next`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "run_not_found",
                    "message": "No encontramos esta corrida."
                  },
                  "timestamp": 1788221700000
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/platform-payouts/{id}/confirm": {
      "post": {
        "operationId": "confirmPlatformPayoutRun",
        "tags": [
          "Platform Payouts"
        ],
        "summary": "Confirm a platform payouts run for stamping",
        "description": "**Irreversible.** Hands a `plan_ready` run to the background worker, which stamps its CFDIs (it runs\nevery minute). A stamped CFDI can only be cancelled, not undone. The response only acknowledges the\nhand-off; follow progress with `GET /platform-payouts/{id}` until `status` is `completed` or\n`failed`, then read its `result`.\n\n**Safe to retry.** Confirming a run that is already `stamping` or `completed` returns its current\nstatus with `200` and does nothing else.\n\n**Provider-months already certified.** Before the run flips to `stamping`, each provider-month it\ncertifies is reserved. If an earlier run of your team (same mode) already reserved a provider-month,\nthis run's retention certificates for it are skipped (their `reason` names the earlier run,\n`reason_code` is `certificate_month_reserved`) and the counts in `included_count`,\n`excluded_count`, `exclusion_summary`, `exclusion_code_summary` and\n`planned_documents.certificate` are recomputed. Income and commission invoices are not affected.\n\nNo request body. Requires `editor` permission on invoices for user-scoped tokens.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Run id.",
            "schema": {
              "type": "string",
              "pattern": "^batchrun_[A-Za-z0-9]{6,40}$"
            },
            "example": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c"
          }
        ],
        "responses": {
          "200": {
            "description": "The run is (or already was) with the worker.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardSuccessResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiPublicPlatformPayoutRunConfirmation"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": "batchrun_3f9a1c7e2b4d6f8a0c1e3a5b7d9f1a2c",
                    "status": "stamping"
                  },
                  "timestamp": 1788221400000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Authentication layer refusal (raw body, see `AuthForbidden`), or the team may no longer use\nplatform payouts: `feature_disabled`, `not_master_team`, `no_billing_account`,\n`team_not_found`, `not_a_member`; or `forbidden` for a user-scoped token without `editor`\npermission on invoices.\n",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/StandardErrorResponse"
                    },
                    {
                      "$ref": "#/components/schemas/AuthMiddlewareError"
                    }
                  ]
                },
                "examples": {
                  "feature_disabled": {
                    "summary": "Platform payouts no longer enabled on the billing account",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "feature_disabled",
                        "message": "La facturación por archivo no está habilitada en esta cuenta. Contacta a soporte."
                      },
                      "timestamp": 1788221400000
                    }
                  },
                  "missing_invoices_permission": {
                    "summary": "User-scoped token without editor permission on invoices",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "forbidden",
                        "message": "This action requires editor access to invoices"
                      },
                      "timestamp": 1788221400000
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No run with this id in your team and mode (`run_not_found`); `resource_not_found` for a\nuser-scoped token whose user is not a member of the team.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "run_not_found",
                    "message": "No encontramos esta corrida."
                  },
                  "timestamp": 1788221400000
                }
              }
            }
          },
          "409": {
            "description": "The run cannot be confirmed. `error.code`:\n\n- `plan_not_ready` - still `planning`; poll `GET /platform-payouts/{id}` and try again.\n- `not_confirmable` - the plan failed (`plan_failed`) or the run already `failed`.\n- `nothing_to_stamp` - the plan issues no document at all.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "examples": {
                  "plan_not_ready": {
                    "summary": "Plan still being computed",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "plan_not_ready",
                        "message": "El plan todavía se está calculando."
                      },
                      "timestamp": 1788221400000
                    }
                  },
                  "not_confirmable": {
                    "summary": "Plan failed, or run failed",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "not_confirmable",
                        "message": "Esta corrida no se puede timbrar."
                      },
                      "timestamp": 1788221400000
                    }
                  },
                  "nothing_to_stamp": {
                    "summary": "The plan has no documents",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "nothing_to_stamp",
                        "message": "No hay documentos que timbrar en este plan."
                      },
                      "timestamp": 1788221400000
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (`internal_server_error`). Retrying is safe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "internal_server_error",
                    "message": "No pudimos confirmar la corrida. Intenta de nuevo."
                  },
                  "timestamp": 1788221400000
                }
              }
            }
          }
        }
      }
    },
    "/platform-payouts/health": {
      "get": {
        "tags": [
          "Platform Payouts"
        ],
        "summary": "Health check",
        "operationId": "platformPayoutsHealth",
        "description": "Liveness probe for the platform payouts module. Unauthenticated.",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "module": "platform-payouts"
                }
              }
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "gigstack Connect",
      "description": "**Multi-Team Resource Access**\n\ngigstack Connect lets a master team act on other teams that share its billing account.\n\n## 🔗 How It Works\n\nAdd the `team` query parameter to a request made with an **API key**:\n\n```bash\n# Access team_xyz789's clients\nGET /clients?team=team_xyz789\n\n# Create an income invoice for team_abc123\nPOST /invoices/income?team=team_abc123\n\n# Update service in team_def456\nPUT /services/service_456?team=team_def456\n```\n\n## ✅ Requirements\n\n- The API key's team must be a master team (gigstack Connect enabled)\n- The target team must exist and share the master team's billing account\n- The plan must include the `multipleIssuerAccounts` feature\n- OAuth access tokens cannot act on another team\n\n## ⚠️ Error Responses\n\nRaw `{ \"message\": … }` bodies from the authentication layer:\n\n- `401 Unauthorized, not a master team` - gigstack Connect not enabled on your key's team\n- `404 Team not found` - Target team doesn't exist\n- `401 Unauthorized, no matched teams` - Target team could not be resolved within your billing account\n- `403 Tu plan no incluye múltiples cuentas emisoras. …` - Plan lacks `multipleIssuerAccounts`\n- `403 Team mismatch with OAuth token` - OAuth access token used with another team's id\n\n## 🌐 Availability\n\nThe `team` parameter is read by the authentication layer, so it is accepted on every authenticated\nendpoint, including ones whose parameter list does not show it.\n"
    },
    {
      "name": "Clients",
      "description": "Client management operations with Mexican tax compliance"
    },
    {
      "name": "Services",
      "description": "Service and product catalog management with SAT product keys"
    },
    {
      "name": "Invoices",
      "description": "Invoice management with CFDI 4.0 compliance and SAT integration"
    },
    {
      "name": "Draft Invoices (Pre-Facturas)",
      "description": "**Create, edit, preview and stamp draft invoices (pre-facturas)**\n\nDraft invoices let you build CFDI invoices incrementally before stamping them with SAT. Use them as **pre-facturas** — generate a preview PDF with a \"Sin Validez Fiscal\" watermark to share with your client for approval, then stamp the draft to create a valid CFDI when ready.\n\n## Typical Workflow\n\n1. `POST /invoices/draft` — Create a draft with minimal data\n2. `PUT /invoices/draft/{id}` — Update as more data becomes available\n3. `POST /invoices/draft/{id}/preview` — Generate a preview PDF (pre-factura)\n4. `POST /invoices/draft/{id}/stamp` — Finalize into a valid CFDI invoice\n"
    },
    {
      "name": "Descarga Masiva SAT",
      "description": "**SAT bulk invoice download via FIEL authentication**\n\nDownload all your issued and received CFDI invoices directly from the SAT (Servicio de Administración Tributaria) using your FIEL (Firma Electrónica Avanzada).\n\n## Setup flow\n1. `GET /invoices/download/activate/status` — Check if activated and what's needed\n2. `POST /invoices/download/activate` — Activate billing (adds Stripe meter/add-on)\n3. `POST /invoices/download/fiel` — Upload `.cer` + `.key` files (auto-registers with SAT)\n4. `PUT /invoices/download/schedule` — Configure daily auto-sync\n5. `POST /invoices/download/request` — Submit manual download requests\n\n## Pricing\n- Included in Pro/Business plans: only the download meter ($0.20 MXN/XML)\n- Other paid plans: the same $0.20 MXN/XML download meter, no monthly base fee\n"
    },
    {
      "name": "Payments",
      "description": "Payment processing, tracking, and refund management"
    },
    {
      "name": "Receipts",
      "description": "Receipt creation and management with CFDI stamping capabilities"
    },
    {
      "name": "Retentions",
      "description": "Tax retention documents (CFDI Retenciones 2.0) — creation, stamping, cancellation, and file retrieval"
    },
    {
      "name": "Platform Payouts",
      "description": "**Plan and stamp a marketplace's provider payouts from two files.**\n\nFor marketplaces and digital platforms that pay providers under the SAT digital-platforms scheme\n(Plataformas Tecnológicas, RESICO 625, retention key 26): ride-hailing drivers, delivery couriers,\nlodging hosts, sellers of goods. Available to marketplace **master teams** whose billing account has\nplatform payouts enabled. Upload a movements file and a commissions file. gigstack matches each row\nto a provider's team in your billing account and plans three kinds of CFDI: the provider's income\ninvoice to you, your retention certificate (key 26) to the provider, and your monthly commission\ninvoice to the provider.\n\n**Not for your own sales.** This is for a platform invoicing on behalf of its providers. A company\ninvoicing its own sales, one CFDI per sale, should use `POST /invoices/income`.\n\n**Tax policy per account.** Which documents are issued, and with which SAT keys and rates, is set\nper master account at onboarding: allowed tax regimes, CSD requirement, service type (`tipoDeServ` /\n`subTipServ`), ISR and IVA withholding rates, product keys and concept descriptions. The defaults are\nfor ground passenger transport (service type `01`, 2.1% ISR withholding). Contact support to\nconfigure your account's policy; it can't be changed through the API.\n\n1. `POST /platform-payouts` with an `Idempotency-Key` - upload and plan (synchronous)\n2. `GET /platform-payouts/{id}` and `GET /platform-payouts/{id}/movements` - review the plan\n3. `POST /platform-payouts/{id}/confirm` - irreversible hand-off to the stamping worker\n4. `GET /platform-payouts/{id}` - poll until `completed` or `failed`, then read `result`\n   (`completed`, `partially_completed` or `failed`)\n\nError messages and exclusion reasons are Spanish sentences for end users; branch on `error.code`,\n`reason_code` and `exclusion_codes`.\n"
    },
    {
      "name": "Documents",
      "description": "SAT supporting documentation (contracts, delivery/payment proofs, communications) — upload\nmetadata, compliance review, AI extraction, and linking to invoices, payments, receipts and clients.\n"
    },
    {
      "name": "Teams",
      "description": "Team management, settings, and member administration"
    },
    {
      "name": "Users",
      "description": "User account management and password operations"
    },
    {
      "name": "Auth",
      "description": "**API-only signup for AI agents and partner integrations.**\n\nA single `POST /v2/auth/signup` call provisions a Firebase Auth user, billing\naccount, team, plan subscription, and returns API keys — no UI, no FIEL upload,\nno human onboarding required.\n\nDesigned for the AI-agents-as-customers use case. RFC defaults to genérico\n(`XAXX010101000`) so agents can transact under público en general until/unless\ntheir customer uploads their own RFC.\n\nAuthenticated with `X-Internal-API-Key` (partner-issued) — Bearer tokens are\nteam-scoped and a brand-new caller doesn't have one yet.\n\nSee `AGENTS.md` in the gigstack-cli repo for end-to-end integration guide.\n"
    },
    {
      "name": "Webhooks",
      "description": "Webhook management for real-time event notifications"
    },
    {
      "name": "Catalogs",
      "description": "**Read-only search over the SAT catalogs**\n\nLook up the SAT codes required on CFDI line items without hardcoding them:\n\n- `GET /catalogs/product-keys` — `c_ClaveProdServ`, the item `product_key`\n- `GET /catalogs/unit-keys` — `c_ClaveUnidad`, the item `unit_key` / `unit_name`\n\nBoth are typo-tolerant full-text searches ranked by relevance. The catalogs are\npublished by the SAT and identical for every team, so results carry no team data\nand ignore `livemode` — but a valid API key is still required.\n"
    },
    {
      "name": "SAT Lists",
      "description": "Read-only access to the RFC lists the SAT publishes under Artículo 69, 69-B and 69-B Bis.\n\ngigstack re-syncs all 22 lists from the SAT's published CSVs every Sunday, so you can screen a counterparty's\nRFC before invoicing it without scraping the SAT yourself.\n"
    }
  ],
  "x-apidog-folder": "Gigstack API v2",
  "x-apidog-orders": [
    "gigstack Connect",
    "Clients",
    "Services",
    "Invoices",
    "Draft Invoices (Pre-Facturas)",
    "Descarga Masiva SAT",
    "Payments",
    "Receipts",
    "Retentions",
    "Platform Payouts",
    "Documents",
    "Teams",
    "Users",
    "Webhooks",
    "Catalogs",
    "SAT Lists"
  ]
}
