> ## Documentation Index
> Fetch the complete documentation index at: https://docs.piriod.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Crear complemento de pago

Emitir **complemento de pago** (SAT México) con Piriod requiere 4 llamadas a la API en la siguiente secuencia:

1. Crear Source
2. Autorizar Payment usando el Source previamente creado
3. Crear Payment Receipt (SAT)
4. Finalizar Payment Receipt (SAT)

<Steps>
  <Step title="Crear un Source">
    En este paso se registra el **origen del pago** en Piriod.

    El `Source` representa la fuente de pago y contiene la información clave del monto, cliente, método y contexto (en este caso, un `offline_payment` vía transferencia bancaria en MXN).

    Aquí todavía **no se está autorizando ni asociando el pago a un pago existente**. Solo se está declarando formalmente el instrumento/origen que luego será utilizado para autorizar el pago.

    Este paso es obligatorio porque el comprobante SAT se genera a partir de un **pago autorizado**, y ese pago debe tener un `source` válido asociado.

    **Output clave que debes guardar:**

    * `source.id` → se utilizará en el Paso 2

    <CodeGroup>
      ```javascript JavaScript theme={null}
      const createSource = async function () {
        const payload = {
          amount: "116000",
          description: "Prueba",
          gateway: "offline_payment",
          offline_payment: {
            currency: "MXN",
            date: "2026-02-24",
            method: "bank_transfer",
          },
          usage: "single",
          customer: "cus_xxxxxxxxx",
        };

        const source = await piriod.resource.create("sources", payload);

        // Guarda el ID para el Paso 2
        console.log("source.id:", source?.id);

        return source;
      };
      ```

      ```python Python theme={null}
      import requests

      def create_source():
          url = f"{BASE_URL}/sources/"
          payload = {
              "amount": "116000",
              "description": "Prueba",
              "gateway": "offline_payment",
              "offline_payment": {
                  "currency": "MXN",
                  "date": "2026-02-24",
                  "method": "bank_transfer",
              },
              "usage": "single",
              "customer": "cus_xxxxxxxxx",
          }

          resp = requests.post(url, json=payload, headers=headers, timeout=30)
          resp.raise_for_status()

          source = resp.json()
          print("source.id:", source.get("id"))
          return source

      # source = create_source()
      ```

      ```shellscript cURL theme={null}
      curl https://api.piriod.com/sources/ \
        -X POST \
        -H "Authorization: your-user-api-key" \
        -H "X-Simple-Workspace: your-organization-id" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": "116000",
          "description": "Prueba",
          "gateway": "offline_payment",
          "offline_payment": {
            "currency": "MXN",
            "date": "2026-02-24",
            "method": "bank_transfer"
          },
          "usage": "single",
          "customer": "cus_xxxxxxxxx"
        }'
      ```
    </CodeGroup>
  </Step>

  <Step title="Autorizar el pago">
    En este paso se **autoriza el pago existente**, asociándolo al `Source` creado previamente.

    La autorización indica que el pago fue validado y aceptado dentro del sistema, cambiando su estado (por ejemplo, a `authorized` o equivalente).

    Sin este paso, el comprobante SAT no puede generarse, ya que únicamente se permite emitirlo sobre pagos autorizados.

    Este es el momento en que:​

    * ​El pago queda formalmente respaldado por un origen de fondos.
    * ​El sistema valida que el monto y el método sean consistentes.

    **Inputs necesarios:**

    * ​`paymentId`
    * ​`sourceId`

    **Output clave a validar:**

    * ​`payment.status` debe reflejar un estado autorizable (ej: `authorized`).

    <CodeGroup>
      ```javascript JavaScript theme={null}
      const authorizePayment = async function ({ paymentId, sourceId }) {
        const payload = {
          source: sourceId,
        };

        const payment = await piriod.resource.create(
          `payments/${paymentId}`,
          payload,
          "authorize"
        );

        console.log("payment.id:", payment?.id);
        console.log("payment.status:", payment?.status);

        return payment;
      };
      ```

      ```python Python theme={null}
      import requests

      def authorize_payment(payment_id: str, source_id: str):
          url = f"{BASE_URL}/payments/{payment_id}/authorize/"
          payload = {"source": source_id}

          resp = requests.post(url, json=payload, headers=headers, timeout=30)
          resp.raise_for_status()

          payment = resp.json()
          print("payment.id:", payment.get("id"))
          print("payment.status:", payment.get("status"))
          return payment

      # payment = authorize_payment(payment_id="pay_lM2nB28b3Nu2yc70LL", source_id="src_xxxxx")
      ```

      ```shellscript cURL theme={null}
      curl https://api.piriod.com/payments/:payment_id/authorize/ \
        -X POST \
        -H "Authorization: your-user-api-key" \
        -H "X-Simple-Workspace: your-organization-id" \
        -H "Content-Type: application/json" \
        -d '{
          "source": "src_xxxxxxxxx"
        }'
      ```
    </CodeGroup>
  </Step>

  <Step title="Crear el complemento de pago">
    En este paso se crea el recurso `payment-receipt`, que representa el **comprobante de pago conforme a SAT México (CFDI de complemento de pago)**.

    Aquí todavía no se timbra ni se finaliza el comprobante; simplemente se genera el registro inicial que vincula el pago autorizado con el documento fiscal correspondiente.

    Este paso:

    * ​Valida que el pago esté autorizado.
    * ​Prepara la estructura fiscal necesaria para el timbrado.
    * ​Genera un `receipt.id` que será utilizado en el paso siguiente.

    **Output clave a guardar:**

    * ​`receipt.id`
    * ​`receipt.status` (usualmente en estado preliminar o pendiente)

    <CodeGroup>
      ```javascript JavaScript theme={null}
      const createPaymentReceipt = async function ({ sourceId }) {
        const payload = {
          sources: [sourceId],
      	tax_settings: {
              mx_payment_form: "03",
              mx_payment_method: "PUE",
              mx_relation: "partial_payment_invoice"
          }
        };

        const receipt = await piriod.resource.create("payment-receipts", payload);

        // Guarda el ID para el Paso 4
        console.log("receipt.id:", receipt?.id);
        console.log("receipt.status:", receipt?.status);

        return receipt;
      ```

      ```python Python theme={null}
      import requests

      def create_payment_receipt(source_id: str):
          url = f"{BASE_URL}/payment-receipts/"
          payload = {
      		"sources": [source_id],
      		"tax_settings": {
      	        "mx_payment_form": "03",
      	        "mx_payment_method": "PUE",
      	        "mx_relation": "partial_payment_invoice"
      	    }
      	}

          resp = requests.post(url, json=payload, headers=headers, timeout=30)
          resp.raise_for_status()

          receipt = resp.json()
          print("receipt.id:", receipt.get("id"))
          print("receipt.status:", receipt.get("status"))
          return receipt

      # receipt = create_payment_receipt(payment_id="pay_lM2nB28b3Nu2yc70LL")
      ```

      ```shellscript cURL theme={null}
      curl https://api.piriod.com/payment-receipts/ \
        -X POST \
        -H "Authorization: your-user-api-key" \
        -H "X-Simple-Workspace: your-organization-id" \
        -H "Content-Type: application/json" \
        -d '{
          "sources": [sou_xxxxxxxxxxxxxx],
      	"tax_settings": {
              "mx_payment_form": "03",
              "mx_payment_method": "PUE",
              "mx_relation": "partial_payment_invoice"
          }
        }'
      ```
    </CodeGroup>
  </Step>

  <Step title="Finalizar el complemento de pago">
    ​Este paso ejecuta el proceso de **finalización y timbrado fiscal** del comprobante ante el SAT.​

    Al finalizar:

    * ​El comprobante se valida fiscalmente.
    * ​Se genera el XML timbrado.
    * ​Se habilita el PDF (si aplica).
    * ​El estado cambia a finalizado (`finalized`, `issued` o similar).

    Este paso es el que convierte el registro preliminar en un documento fiscal válido ante el SAT.

    Después de esta operación, el comprobante:

    * ​No debería modificarse.
    * ​Puede ser descargado o enviado al cliente.
    * ​Queda registrado oficialmente como CFDI de complemento de pago.

    **Output esperado:**

    * ​`receipt.status` final.
    * ​`xml_url` y/o `pdf_url` (si el API los expone).

    <CodeGroup>
      ```javascript JavaScript theme={null}
      const finalizePaymentReceipt = async function ({ receiptId }) {
        const finalized = await piriod.resource.get(
          "payment-receipts",
          receiptId,
          "finalize"
        );

        console.log("finalized.id:", finalized?.id);
        console.log("finalized.status:", finalized?.status);

        return finalized;
      };
      ```

      ```python Python theme={null}
      import requests

      def finalize_payment_receipt(receipt_id: str):
          url = f"{BASE_URL}/payment-receipts/{receipt_id}/finalize/"

          resp = requests.get(url, headers=headers, timeout=30)
          resp.raise_for_status()

          finalized = resp.json()
          print("finalized.id:", finalized.get("id"))
          print("finalized.status:", finalized.get("status"))

          return finalized

      # finalized = finalize_payment_receipt(receipt_id="prc_xxxxx")
      ```

      ```shellscript cURL theme={null}
      curl https://api.piriod.com/payment-receipts/:payment_receipt_id/finalize/ \
        -X GET \
        -H "Authorization: your-user-api-key" \
        -H "X-Simple-Workspace: your-organization-id" \
      ```
    </CodeGroup>
  </Step>
</Steps>
