Releases: frain-dev/convoy-python
Releases · frain-dev/convoy-python
Release list
v1.0.0a1
What's new
- OpenAPI-generated API client (
AuthenticatedClient+convoy.api.*) via openapi-python-client - Hand-written webhook verification unchanged at
convoy.utils.webhook(fail-closed bool) - Requires Python 3.11+
Install (pre-release)
pip install --pre convoy-python
# or
pip install convoy-python==1.0.0a1Plain pip install convoy-python still resolves to 0.2.0 until a final 1.0.0 is cut.
Migration: 0.2.0 → 1.0.0
1.0.0 is a full rewrite. The hand-written client is removed and replaced with a client generated from Convoy's OpenAPI spec via openapi-python-client. Webhook signature verification remains hand-written at the same import path, with a stricter, fail-closed contract.
The first release is published as a pre-release (1.0.0a1), so plain pip install convoy-python keeps resolving to 0.2.0 until a final 1.0.0 is cut. Install the pre-release explicitly.
Breaking changes
- Python 3.11 or newer is required. 0.2.0 ran on any Python 3.
- Dependencies changed from
requeststohttpxandattrs. - The
Convoyfacade class is gone. There is nofrom convoy import Convoyanymore. You construct anAuthenticatedClientand call per-operation module functions. - Client construction and auth. 0.2.0 took a config dict with
api_key,uri, andproject_id(and documented but effectively unusedusername/passwordbasic auth keys, which are dropped entirely). 1.0.0 usesAuthenticatedClient(base_url=..., token=...). The base URL no longer includes/v1and no longer embeds the project ID; generated paths look like/v1/projects/{project_id}/..., so pass the instance API root, for examplehttps://us.getconvoy.cloud/api. - Project ID moved from the client to each call. Every operation takes
project_idas its first argument. - Methods are now module-level functions, not attribute methods.
convoy.event.create(query, data)style calls are replaced byfrom convoy.api.events import create_endpoint_event; create_endpoint_event.sync(project_id, client=client, body=...). Each operation module exposes four callables:sync,sync_detailed,asyncio, andasyncio_detailed. Async support is new in 1.0.0. - Requests and responses are typed attrs models, not dicts and tuples. 0.2.0 returned
(json_dict, status_code)tuples. 1.0.0sync/asyncioreturn a parsed model for the documented status codes (for exampleCreateEndpointEventResponse201);sync_detailed/asyncio_detailedreturn aResponseobject withstatus_code,content,headers, andparsed. Build request bodies with model classes such asconvoy.models.ModelsCreateEvent. - The
groupAPI is gone. Server-side, groups became projects; use the functions underconvoy.api.projects. batchresendno longer exists under that name. Useconvoy.api.event_deliveries.batch_retry_event_delivery(filters are query parameters) orforce_resend_event_deliveries(takes a body of IDs).- Webhook verification fails closed and returns a strict bool. In 0.2.0,
verify_signaturecould return a truthy error-message string on failure, which madeif webhook.verify_signature(...)pass for invalid signatures. In 1.0.0 it returnsTrueorFalse, never a string, and malformed input returnsFalseinstead of raising unexpected errors. If you relied on inspecting returned error strings, switch to a plain boolean check. Supported hash algorithms are now restricted tosha256andsha512(the only algorithms Convoy signs with); passingmd5,sha1, or other algorithms now raisesValueError.
Method mapping
| 0.2.0 | 1.0.0 (call .sync(...) or .asyncio(...)) |
|---|---|
convoy.endpoint.all(query) |
convoy.api.endpoints.get_endpoints |
convoy.endpoint.create(query, data) |
convoy.api.endpoints.create_endpoint |
convoy.endpoint.find(id, query) |
convoy.api.endpoints.get_endpoint |
convoy.endpoint.update(id, query, data) |
convoy.api.endpoints.update_endpoint |
convoy.endpoint.delete(id, query, data) |
convoy.api.endpoints.delete_endpoint |
convoy.event.all(query) |
convoy.api.events.get_events_paged |
convoy.event.create(query, data) |
convoy.api.events.create_endpoint_event |
convoy.event.find(id, query) |
convoy.api.events.get_endpoint_event |
convoy.event_delivery.all(query) |
convoy.api.event_deliveries.get_event_deliveries_paged |
convoy.event_delivery.find(id, query) |
convoy.api.event_deliveries.get_event_delivery |
convoy.event_delivery.resend(id, query) |
convoy.api.event_deliveries.resend_event_delivery |
convoy.event_delivery.batchresend(id, query, data) |
convoy.api.event_deliveries.batch_retry_event_delivery |
convoy.delivery_attempt.* |
convoy.api.delivery_attempts.get_delivery_attempts / get_delivery_attempt |
convoy.source.* |
convoy.api.sources.* |
convoy.subscription.* |
convoy.api.subscriptions.* |
convoy.group.* |
convoy.api.projects.* (groups are now projects) |
convoy.webhook |
convoy.utils.webhook.Webhook (same import path as before) |
Before and after
Install:
# 0.2.0
pip install convoy-python
# 1.0.0 (pre-release)
pip install --pre convoy-pythonClient setup:
# 0.2.0
from convoy import Convoy
convoy = Convoy({
"api_key": "your_api_key",
"uri": "https://us.getconvoy.cloud/api/v1",
"project_id": "your_project_id",
})
# 1.0.0
from convoy import AuthenticatedClient
client = AuthenticatedClient(
base_url="https://us.getconvoy.cloud/api", # no /v1, no project id
token="your_api_key",
)
project_id = "your_project_id"Create an endpoint:
# 0.2.0
(response, status) = convoy.endpoint.create({}, {
"name": "default-endpoint",
"url": "https://example.com/webhooks/convoy",
"secret": "endpoint-secret",
})
endpoint_id = response["data"]["uid"]
# 1.0.0
from convoy.api.endpoints import create_endpoint
from convoy.models import ModelsCreateEndpoint
result = create_endpoint.sync(project_id, client=client, body=ModelsCreateEndpoint(
name="default-endpoint",
url="https://example.com/webhooks/convoy",
secret="endpoint-secret",
))
endpoint_id = result.data.uidSend an event (sync and async):
from convoy.api.events import create_endpoint_event
from convoy.models import ModelsCreateEvent, ModelsCreateEventDataType0
body = ModelsCreateEvent(
endpoint_id=endpoint_id,
event_type="payment.success",
data=ModelsCreateEventDataType0.from_dict({"status": "Completed"}),
)
# sync
result = create_endpoint_event.sync(project_id, client=client, body=body)
# async
result = await create_endpoint_event.asyncio(project_id, client=client, body=body)List event deliveries:
# 0.2.0
(response, status) = convoy.event_delivery.all({"perPage": 20})
# 1.0.0
from convoy.api.event_deliveries import get_event_deliveries_paged
result = get_event_deliveries_paged.sync(project_id, client=client, per_page=20)
deliveries = result.data.contentVerify a webhook signature:
# import path unchanged
from convoy.utils.webhook import Webhook
webhook = Webhook(secret="endpoint-secret")
payload = request.body.decode("utf-8")
signature = request.headers.get("X-Convoy-Signature", "")
if not webhook.verify_signature(payload, signature):
# reject the request; verify_signature now returns a strict bool
...v0.2.0
v0.1.1
What's Changed
- Update README.md by @Youngestdev in #1
- Convoy 0.6 support by @Youngestdev in #2
- Convoy 0.6 patch by @Youngestdev in #3
New Contributors
- @Youngestdev made their first contribution in #1
Full Changelog: v0.1.0...v0.2.0