Skip to main content
Glama

create_invoice

Generate ZATCA-compliant invoices in Stream by specifying customer details, line items, and payment options. Send invoices directly to customers and schedule delivery dates.

Instructions

Create a ZATCA-compliant invoice in Stream.

items is a list of line-item dicts, each with:

  • product_id (str, required)

  • quantity (int > 0, required)

scheduled_on is the ISO-8601 date-time for when the invoice is due/sent. Set notify_consumer to True to send the invoice to the customer.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
customer_idYes
itemsYes
scheduled_onNo
descriptionNo
currencyNoSAR
notify_consumerNo
couponsNo
accept_madaNo
accept_visaNo
accept_mastercardNo
accept_amexNo
accept_bank_transferNo
accept_installmentNo

Implementation Reference

  • The main handler function create_invoice that creates a ZATCA-compliant invoice in Stream. It accepts customer_id, items (list of dicts with product_id and quantity), scheduled_on, description, currency, notify_consumer, coupons, and various payment method acceptance flags. The function validates items, creates a payment methods object, builds the request body, calls the Stream API via client.post(), and handles errors.
    async def create_invoice(
        customer_id: str,
        items: list[dict],
        scheduled_on: str | None = None,
        description: str | None = None,
        currency: str = "SAR",
        notify_consumer: bool = True,
        coupons: list[str] | None = None,
        accept_mada: bool = True,
        accept_visa: bool = True,
        accept_mastercard: bool = True,
        accept_amex: bool = False,
        accept_bank_transfer: bool = False,
        accept_installment: bool = False,
        ctx: Context = None,  # type: ignore[assignment]
    ) -> dict[str, Any]:
        """Create a ZATCA-compliant invoice in Stream.
    
        *items* is a list of line-item dicts, each with:
          - product_id  (str, required)
          - quantity    (int > 0, required)
    
        *scheduled_on* is the ISO-8601 date-time for when the invoice is due/sent.
        Set *notify_consumer* to True to send the invoice to the customer.
        """
        parsed_items = [InvoiceItemCreateDto(**item) for item in items]
        if scheduled_on is None:
            scheduled_on = datetime.now(timezone.utc).isoformat()
        payment_methods = InvoicePaymentMethodDto(
            mada=accept_mada,
            visa=accept_visa,
            mastercard=accept_mastercard,
            amex=accept_amex,
            bank_transfer=accept_bank_transfer,
            installment=accept_installment,
        )
        body = CreateInvoiceRequest(
            organization_consumer_id=customer_id,
            items=parsed_items,
            payment_methods=payment_methods,
            scheduled_on=scheduled_on,
            notify_consumer=notify_consumer,
            description=description,
            coupons=coupons,
            currency=currency,
        )
        client = await get_client(ctx)
        try:
            return await client.post(_BASE, body.model_dump(exclude_none=True))
        except StreamAPIError as exc:
            return _err(exc)
  • Pydantic BaseModel defining the request structure for creating a new invoice. Includes fields: organization_consumer_id (required), items (list of InvoiceItemCreateDto, required), payment_methods (InvoicePaymentMethodDto), scheduled_on (ISO-8601 date-time, required), notify_consumer (boolean), description (string up to 500 chars), coupons (list of strings), and currency (ISO-4217 code, defaults to 'SAR').
    class CreateInvoiceRequest(BaseModel):
        """Request body for creating a new invoice."""
    
        organization_consumer_id: str = Field(..., description="Customer (consumer) ID to invoice.")
        items: list[InvoiceItemCreateDto] = Field(..., min_length=1, description="Line-items on the invoice.")
        payment_methods: InvoicePaymentMethodDto = Field(
            default_factory=InvoicePaymentMethodDto,
            description="Payment methods accepted for this invoice.",
        )
        scheduled_on: str = Field(..., description="ISO-8601 date-time when the invoice should be sent/due.")
        notify_consumer: bool = Field(default=True, description="Send the invoice to the customer upon creation.")
        description: str | None = Field(default=None, max_length=500, description="Invoice memo / description.")
        coupons: list[str] | None = Field(default=None, description="Coupon IDs to apply to the whole invoice.")
        currency: str = Field(default="SAR", description="ISO-4217 currency code.")
  • Pydantic BaseModel for a single line-item on an invoice. Requires product_id (string) and quantity (integer > 0). Also accepts an optional coupons field for coupon IDs to apply specifically to this item.
    class InvoiceItemCreateDto(BaseModel):
        """A single line-item on an invoice."""
    
        product_id: str = Field(..., description="ID of the product.")
        quantity: int = Field(..., gt=0, description="Quantity (> 0).")
        coupons: list[str] | None = Field(default=None, description="Coupon IDs to apply to this item.")
  • Pydantic BaseModel defining payment methods accepted for an invoice. Contains boolean fields for: mada, visa, mastercard, amex, bank_transfer, installment, and qurrah. All default to False except mada, visa, and mastercard which default to True.
    class InvoicePaymentMethodDto(BaseModel):
        """Payment methods accepted for an invoice."""
    
        mada: bool = Field(default=True, description="Accept Mada payments.")
        visa: bool = Field(default=True, description="Accept Visa payments.")
        mastercard: bool = Field(default=True, description="Accept Mastercard payments.")
        amex: bool = Field(default=False, description="Accept Amex payments.")
        bank_transfer: bool = Field(default=False, description="Accept bank transfer.")
        installment: bool = Field(default=False, description="Accept installment payments.")
        qurrah: bool = Field(default=False, description="Accept Qurrah payments.")
  • The register function that registers all invoice tools on the FastMCP instance. This function contains the @mcp.tool decorator on create_invoice, which is where the tool is registered with the MCP server. The function also defines helper _err for error handling.
    def register(mcp: FastMCP) -> None:
        """Register all invoice tools on *mcp*."""
    
        @mcp.tool
        async def create_invoice(
            customer_id: str,
            items: list[dict],
            scheduled_on: str | None = None,
            description: str | None = None,
            currency: str = "SAR",
            notify_consumer: bool = True,
            coupons: list[str] | None = None,
            accept_mada: bool = True,
            accept_visa: bool = True,
            accept_mastercard: bool = True,
            accept_amex: bool = False,
            accept_bank_transfer: bool = False,
            accept_installment: bool = False,
            ctx: Context = None,  # type: ignore[assignment]
        ) -> dict[str, Any]:
            """Create a ZATCA-compliant invoice in Stream.
    
            *items* is a list of line-item dicts, each with:
              - product_id  (str, required)
              - quantity    (int > 0, required)
    
            *scheduled_on* is the ISO-8601 date-time for when the invoice is due/sent.
            Set *notify_consumer* to True to send the invoice to the customer.
            """
            parsed_items = [InvoiceItemCreateDto(**item) for item in items]
            if scheduled_on is None:
                scheduled_on = datetime.now(timezone.utc).isoformat()
            payment_methods = InvoicePaymentMethodDto(
                mada=accept_mada,
                visa=accept_visa,
                mastercard=accept_mastercard,
                amex=accept_amex,
                bank_transfer=accept_bank_transfer,
                installment=accept_installment,
            )
            body = CreateInvoiceRequest(
                organization_consumer_id=customer_id,
                items=parsed_items,
                payment_methods=payment_methods,
                scheduled_on=scheduled_on,
                notify_consumer=notify_consumer,
                description=description,
                coupons=coupons,
                currency=currency,
            )
            client = await get_client(ctx)
            try:
                return await client.post(_BASE, body.model_dump(exclude_none=True))
            except StreamAPIError as exc:
                return _err(exc)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/streampayments/stream'

If you have feedback or need assistance with the MCP directory API, please join our Discord server