Skip to main content

helpvox — Python SDK for the HelpVox app platform

Build apps that plug into HelpVox: install via OAuth, receive events, give the AI agent tools, embed a dashboard page and call the REST API. Python 3.9+, no dependencies.

pip install helpvox

The wire contract this SDK follows is in docs/apps/platform-contract.md. You need your app's client_id (hvapp_…) and client_secret (hvs_…). The secret is the HMAC key for everything HelpVox sends you — keep it in one environment variable.

Install (OAuth)

Send the merchant to the consent screen, then exchange the code on your callback:

import helpvox

url = helpvox.install_url("loyalty-points", redirect_url="https://app.example/oauth/callback", state=csrf)

# GET /oauth/callback?code=hvic_…&installation_id=…&state=…
token = helpvox.exchange_code(CLIENT_ID, CLIENT_SECRET, code)
# {"access_token": "hva_…", "token_type": "bearer", "scope": "…", "installation_id": "…", "vendor_id": "…"}
store(token["installation_id"], token["access_token"])

# Your agent tools stay off until you say you are ready:
helpvox.Client(token["access_token"]).ready()

Codes live 10 minutes and work once — exchanging the same code twice revokes the installation. Failures raise helpvox.ApiError (e.code == "invalid_grant").

Events

Always verify against the raw request body.

from helpvox import parse_event, SignatureError

try:
    event = parse_event(CLIENT_SECRET, raw_body, request_headers)
except SignatureError:
    return 401

if already_processed(event.id):   # the same id is sent on every retry
    return 200
if event.type == "order.status_changed":
    ...
elif event.type == "app.uninstalled":
    delete_data(event.installation_id)

Event has id, type, created_at, vendor_id, installation_id, data, is_test. Header lookup is case-insensitive and accepts any dict-like headers object. Answer 2xx within 10 seconds. Send yourself a sample with client.send_test_event("order.created") (event.is_test is True).

Agent tools

Your handler gets (input, context) and returns plain text for the agent (cut to 2000 characters), or raises ToolError with a short reason the agent can tell the customer.

from helpvox import ToolContext, ToolError, handle_tool_call

def get_balance(input: dict, ctx: ToolContext) -> str:
    points = lookup(ctx.installation_id, input["phone"])
    if points is None:
        raise ToolError("There is no loyalty account for this phone number.")
    return f"The customer has {points} points."

handle_tool_call returns (status, json_body): 401 for a bad signature, 400 for a malformed body, otherwise 200 with {"result": …} or {"error": …}. Other exceptions propagate; HelpVox then continues without the tool. ToolContext has tool, installation_id, vendor_id, channel, conversation_id, language, country, caller_phone.

Flask:

from flask import Flask, jsonify, request

app = Flask(__name__)

@app.post("/tools/balance")
def balance():
    status, body = handle_tool_call(CLIENT_SECRET, request.get_data(), request.headers, get_balance)
    return jsonify(body), status

FastAPI:

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.post("/tools/balance")
async def balance(request: Request):
    status, body = handle_tool_call(CLIENT_SECRET, await request.body(), request.headers, get_balance)
    return JSONResponse(body, status_code=status)

Phone tools have 1500 ms by default, so keep the handler fast (if it blocks, run it in a thread pool in async frameworks). Events work the same way: parse_event(CLIENT_SECRET, request.get_data(), request.headers).

Dashboard page

If your manifest sets ui.settings_page, HelpVox embeds it with ?installation_id=…&session=<JWT>. The token lives 60 seconds — verify it, then start your own session:

from helpvox import verify_session_token

claims = verify_session_token(CLIENT_SECRET, request.args["session"], CLIENT_ID)
if claims is None:
    abort(401)
login(installation_id=claims["installation_id"], user=claims["sub"], lang=claims["lang"])

sign_session_token(secret, claims) issues one the same way HelpVox does, for your tests.

REST API

from helpvox import ApiError, Client

client = Client(access_token)

client.app()                          # installation, vendor, scopes, ready, capabilities
orders = client.orders(status="new", limit=50)
client.order(order_id)
client.update_order(order_id, {"note": "Gift wrap"})          # orders:write
client.products(); client.calls(); client.call(call_id)
client.callbacks(); client.appointments()

d = client.create_discount(conversation_id, 12.00, "EUR", "Loyalty points", reference="ledger-42")
client.discount(d["id"]); client.cancel_discount(d["id"])

# anything else
client.request("GET", "/api/v1/categories")

try:
    client.calls()
except ApiError as e:
    print(e.status, e.code, e.message, e.scope)   # 403 insufficient_scope … conversations:read

Customer fields are removed from responses without customers:read; transcripts without transcripts:read.

For tests, pass transport= — a callable (method, url, headers, body_bytes) -> (status, body_bytes) — to Client or exchange_code. Signatures: helpvox.sign(secret, body) / helpvox.verify(secret, body, header).

Development

cd sdk/python
python3 -m unittest discover -s tests

Metadata

Release files for helpvox 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for helpvox 0.1.0
File Size Uploaded Provenance
helpvox-0.1.0.tar.gz 14.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for helpvox 0.1.0
File Interpreter ABI Platform
helpvox-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 30.1 kB

Release files / helpvox-0.1.0.tar.gz

Download URL helpvox-0.1.0.tar.gz
Size 14.9 kB
Tags Source
SHA-256 checksum
How to use checksums
cc76b46e76a4733b241d14ab528d99697665f6f65d17fd42e064e336f05005cc
BLAKE2b-256 checksum
How to use checksums
4e34aaf8b0e22d5ef250c9a3f39f8732dd0dc3d67e4664c10f0127cf70556e22
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / helpvox-0.1.0-py3-none-any.whl

Download URL helpvox-0.1.0-py3-none-any.whl
Size 15.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1f5785d64bb4b94ab52ef77a1796fa2e293b7335427f009170c13edee10fc2ed
BLAKE2b-256 checksum
How to use checksums
c05844ed0b769590748ea32d19743af11e22b41986bfad5268682387fe32bb63
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Security for helpvox 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page