Skip to main content

Python SDK package for invoq server APIs and webhook verification.

Project description

invoq Python SDK

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.

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, payment_status, project, deposit_address, monitoring_ends_at, 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.

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.1.0.tar.gz (17.4 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.1.0-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for invoq-0.1.0.tar.gz
Algorithm Hash digest
SHA256 018ac3a4d6f371a4a719d09493724c61988fd9b666771a957e04f64c0c52a37a
MD5 baa20979450b469bbae37c6c007c77bf
BLAKE2b-256 b2aaeb8411db9198989feacb6eda0863c71b2adf88c55a94de7ef74d737acc93

See more details on using hashes here.

File details

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

File metadata

  • Download URL: invoq-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.5 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 460dbc6c43f1efdbb45dcdf50fe24d33f4490300d5ccf53c2e196af3eaa9271b
MD5 c23d7c1ae52d6d8861ea4047b8474d63
BLAKE2b-256 521e4a78d728a5847d87591783116912b89332c45e860bc15f75026c9b3bbd9a

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