Skip to main content

Python SDK package for invoq server APIs and webhook verification.

Project description

invoq Python SDK

English · Bahasa Indonesia · Español · Français · Português · Tiếng Việt · Türkçe · ไทย · 简体中文 · 繁體中文

Python SDK for invoq server APIs and webhook verification. Create stablecoin invoices from your backend and fulfill orders with signed webhooks.

Use this package only on your server. It accepts secret keys and must not be bundled into browser code.

Server SDKs

Create invoices and verify webhooks from your backend in any of these languages — same REST API, same webhook signature. This repository is the Python SDK.

Language Repository
Node.js github.com/invoqmoney/sdk-js (@invoq/server)
Python this repo
PHP github.com/invoqmoney/sdk-php
Go github.com/invoqmoney/sdk-go
Rust github.com/invoqmoney/sdk-rust
Ruby github.com/invoqmoney/sdk-ruby

The browser side is the same for every backend: @invoq/checkout (JavaScript, in github.com/invoqmoney/sdk-js) opens the in-page checkout modal for any frontend.

Installation

python -m pip install invoq

Requires Python 3.9 or newer.

Get your keys

  1. Sign in to the invoq dashboard and create a project.
  2. On the API keys page, create a secret key. Test keys start with sk_test_, live keys with sk_live_.
  3. In your project's webhooks settings, save your webhook URL and store the webhook secret (whsec_...) for that mode.

Add both to your server environment:

INVOQ_SECRET_KEY=sk_test_...
INVOQ_WEBHOOK_SECRET=whsec_...

Start with test keys. Switch to the live key and live webhook secret when you go to production.

Create a client

import os

from invoq import Invoq

invoq = Invoq(os.environ["INVOQ_SECRET_KEY"])

Production API default:

https://api.invoq.money

Override the API origin and request timeout during development:

invoq = Invoq(
    os.environ["INVOQ_SECRET_KEY"],
    api_origin="http://localhost:8787",
    timeout_ms=10_000,
)

api_origin must be an absolute http or https origin with no path, query, hash, username, or password. The SDK appends /v1/... API paths. Requests time out after 10 seconds by default (timeout_ms).

Invoices

Create an invoice:

invoice = invoq.invoices.create({
    "amount": "149",
    "currency": "USD",
    "description": "SaaS boilerplate",
    "reference_id": "order_1234",
    "return_url": "https://merchant.example/thanks",
})

Notes:

  • Use a server-side amount. Do not trust client-supplied amounts.
  • amount is a decimal USD string from "0.01" to "999.99" with up to 2 decimal places, such as "129" or "129.99".
  • Use reference_id to map invoice.paid webhooks back to your order. It also makes creation retry-safe: creating again with the same reference_id and the same invoice terms returns the existing invoice instead of a duplicate, while different terms fail with a 409 reference_id_conflict API error.
  • Omit return_url to use the project's default return URL. Pass None to send JSON null and create the invoice without a return URL. On reference_id retries, pass return_url explicitly when you need to assert a specific value.
  • description and reference_id must be strings when present.

Get an invoice:

invoice = invoq.invoices.get("inv_123")

invoices.get() returns the public invoice shape used by the hosted checkout endpoint. It includes checkout-facing fields such as amount_paid, amount_due, amount_overpaid, payment_status, project, deposit_address, monitoring_ends_at, monitoring_status, transfers, and direct_onchain_rails, but does not include reference_id. Use the create response or the invoice.paid webhook when you need your merchant reference_id.

Create a test payment:

paid_invoice = invoq.invoices.create_test_payment("inv_123", {
    "amount": "149",
    "reference_id": "test_payment_001",
})

create_test_payment only works on invoices created with a sk_test_ key. When payments reach the invoice amount, the invoice becomes paid and invoq sends a real signed invoice.paid webhook to your test webhook URL. Partial amounts are allowed and produce partially_paid.

Amounts in responses are normalized to 4 decimal places: create with "129" and the invoice returns amount: "129.0000". Compare amounts numerically, not as strings. amount_due is derived as max(amount - amount_paid, 0) and uses the same 18-decimal scale as amount_paid; amount_overpaid is its mirror, max(amount_paid - amount, 0), so you never subtract money yourself. monitoring_status is "active" or "ended" — once it is "ended", the deposit address is no longer watched — and transfers is the confirmed on-chain receipt trail (each entry has tx_hash, amount, and explorer_tx_url). Both are None / [] for test invoices.

The SDK returns the response data object directly.

Hosted checkout page

Every invoice also has a hosted checkout page at:

https://pay.invoq.money/<invoice id>

Share the link or redirect to it when an in-page checkout modal is not a fit.

Webhooks

Pass the raw request body to verify_webhook. Do not parse JSON and re-dump it before verification.

import os

from invoq import is_invoice_paid, verify_webhook

event = verify_webhook(
    raw_body,
    {"invoq-signature": signature_header},
    os.environ["INVOQ_WEBHOOK_SECRET"],
)

if is_invoice_paid(event):
    order_id = event["data"]["invoice"]["reference_id"]

    if order_id is None:
        raise ValueError("Missing invoice reference_id for fulfillment.")

    fulfill_order(order_id)

Use invoice.paid webhooks to fulfill orders on your server. When is_invoice_paid(event) is true, the invoice is ready for automatic fulfillment; use the invoice reference_id to find and fulfill your order. The helper accepts paid-equivalent invoice statuses (paid, settling, or settled) and rejects review_required.

Important:

  • Pass the raw request body as a string or bytes.
  • Pass a header mapping with the invoq-signature header.
  • Do not parse JSON and re-dump it before verification.
  • verify_webhook does not require Invoq(...) or your invoq API secret key.
  • Use your webhook secret, not INVOQ_SECRET_KEY.
  • Fulfill idempotently. Failed webhook deliveries are retried.
  • Respond with a 2xx quickly. Other statuses count as failed deliveries.

Webhook verification failures raise InvoqSignatureVerificationError. The signature header is:

invoq-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">

Errors

from invoq import InvoqApiError, InvoqError

try:
    invoq.invoices.create({"amount": "0.001", "currency": "USD"})
except InvoqApiError as error:
    print(error.status)
    print(error.code)
    print(error.fields)
except InvoqError:
    raise

Non-2xx API responses raise InvoqApiError, which has status, code, fields, meta, and the raw payload. Connection failures, timeouts, response parse failures, and invalid SDK inputs raise InvoqError.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

invoq-0.2.0.tar.gz (18.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

invoq-0.2.0-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

Details for the file invoq-0.2.0.tar.gz.

File metadata

  • Download URL: invoq-0.2.0.tar.gz
  • Upload date:
  • Size: 18.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for invoq-0.2.0.tar.gz
Algorithm Hash digest
SHA256 395a4281234bfde372b083edc4574429184b136dff6815303a62040d9530f8bb
MD5 a3ead92aac5f618dd5e41c851a3f6da0
BLAKE2b-256 73092f15f35103f72cafe38132c7efb4955fb8ca600a14eca04af814e3af3696

See more details on using hashes here.

File details

Details for the file invoq-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: invoq-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for invoq-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2f17641a7f87f5bfbe8ec8e928f30bd8b8402c45746e3bd7817df43f7d075978
MD5 a2b207be39e12f265d7f93f2e0da5578
BLAKE2b-256 caad4acb87a04a208f1b660cfff3d03b8fb3973518c5b44e565432b9fc878587

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page