Skip to main content

Python SDK for the Rangler API.

Project description

ranglerpy

ranglerpy is a Python SDK for the Rangler API.

It is designed around the actual Rangler product shape:

  • polling-first event consumption
  • optional webhook verification helpers
  • thin wrappers for the developer control plane

The goal is to make Rangler easy to integrate whether you want to:

  • poll event feeds with a cursor
  • consume companies and filings directly
  • manage webhook endpoints and event subscriptions
  • verify Rangler webhook signatures in a receiver

It is designed to give you one integration surface across:

  • polling feeds
  • webhook delivery
  • developer control-plane operations

Installation

With uv:

uv add ranglerpy

With pip:

pip install ranglerpy

For local development:

pip install -e .[dev]

For release builds:

python scripts/update_version.py 0.1.1
python -m unittest discover -s tests -v
uv build --no-sources
UV_PUBLISH_TOKEN=pypi-your-project-token uv publish

For local checks with the PyPA tools:

pip install -e .[build]
python -m build
python -m twine check dist/*

Quick start

Data plane: polling events

from ranglerpy import InMemoryCursorStore, PollingConsumer, RanglerClient

client = RanglerClient(
    api_key="rgl_test_your_api_key",
    environment="sandbox",
)

consumer = PollingConsumer(
    client.v1.events,
    cursor_store=InMemoryCursorStore(),
    stream="market-wide-filings",
)

for event in consumer.poll(event_types=["filing.new"], limit=100):
    print(event.id, event.type, event.occurred_at.isoformat())

Async polling

from ranglerpy import AsyncPollingConsumer, AsyncRanglerClient, FileCursorStore

async with AsyncRanglerClient(
    api_key="rgl_test_your_api_key",
    environment="sandbox",
) as client:
    consumer = AsyncPollingConsumer(
        client.v1.events,
        cursor_store=FileCursorStore(".rangler-cursors.json"),
        stream="issuer-monitoring",
    )

    for event in await consumer.poll(
        limit=100,
        event_types=["filing.new"],
    ):
        print(event.id, event.type)

Control plane: manage webhooks

from ranglerpy import RanglerClient

client = RanglerClient(
    bearer_token="your_portal_bearer_token",
    environment="live",
)

organization = client.organizations.create(
    name="Rangler Demo Org",
    billing_email="billing@example.com",
)

webhook = client.webhooks.create(
    organization["id"],
    url="https://example.com/rangler/webhooks",
)

print(webhook["signing_secret"])

Webhook verification

from ranglerpy import InMemoryIdempotencyStore, Webhook

idempotency_store = InMemoryIdempotencyStore()

event = Webhook.construct_event(
    headers=headers,
    raw_body=raw_body,
    secret=webhook_secret,
    idempotency_store=idempotency_store,
)

print(event.type, event.display.title, event.data.object.id)

FastAPI webhook handler

from fastapi import FastAPI, HTTPException, Request

from ranglerpy import DuplicateEventError, InMemoryIdempotencyStore, InvalidSignatureError, Webhook

app = FastAPI()
store = InMemoryIdempotencyStore()


@app.post("/rangler/webhooks")
async def rangler_webhook(request: Request):
    raw_body = await request.body()

    try:
        event = Webhook.construct_event(
            headers=request.headers,
            raw_body=raw_body,
            secret="whsec_your_secret",
            idempotency_store=store,
        )
    except InvalidSignatureError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    except DuplicateEventError:
        return {"duplicate": True}

    return {"received": event.id}

Flask webhook handler

from flask import Flask, jsonify, request

from ranglerpy import DuplicateEventError, InMemoryIdempotencyStore, InvalidSignatureError, Webhook

app = Flask(__name__)
store = InMemoryIdempotencyStore()


@app.post("/rangler/webhooks")
def rangler_webhook():
    raw_body = request.get_data()

    try:
        event = Webhook.construct_event(
            headers=request.headers,
            raw_body=raw_body,
            secret="whsec_your_secret",
            idempotency_store=store,
        )
    except InvalidSignatureError as exc:
        return jsonify({"error": str(exc)}), 400
    except DuplicateEventError:
        return jsonify({"duplicate": True}), 200

    return jsonify({"received": event.id})

Authentication modes

Rangler has two auth modes:

  • data plane uses X-API-Key
  • developer control plane uses Authorization: Bearer ...

ranglerpy supports both on the same client. Resource methods choose the correct auth mode internally.

Current SDK scope

Data plane

  • companies
  • filings
  • funds
  • event feeds

Control plane

  • organizations
  • API keys
  • usage and billing status
  • webhook endpoints
  • webhook deliveries
  • event subscriptions

Helpers

  • cursor-based event iteration
  • Stripe-style client.v1.* namespace
  • list responses with data
  • dynamic object access for webhook/API payloads, e.g. event.data.object.id
  • polling consumer with checkpoint persistence
  • Rangler webhook signature verification
  • Webhook.construct_event(...) for webhook receivers
  • in-memory idempotency helper for duplicate webhook handling
  • async client support

Example scripts

The repo includes runnable examples in examples/:

These are intentionally small. They are meant to be copied into a real worker, cron job, or receiver and then adapted to your own storage and job queue.

Notes

This first version is intentionally thin. It aims to give Rangler customers one integration surface across polling and webhooks instead of pushing everyone straight into raw HTTP and receiver boilerplate.

You can override base_url explicitly if you need to point the SDK at a different Rangler environment.

The package version is tracked in VERSION, pyproject.toml, and src/ranglerpy/_version.py. The API contract version is tracked separately in src/ranglerpy/_api_version.py.

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

ranglerpy-0.1.1.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

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

ranglerpy-0.1.1-py3-none-any.whl (25.1 kB view details)

Uploaded Python 3

File details

Details for the file ranglerpy-0.1.1.tar.gz.

File metadata

  • Download URL: ranglerpy-0.1.1.tar.gz
  • Upload date:
  • Size: 18.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.17

File hashes

Hashes for ranglerpy-0.1.1.tar.gz
Algorithm Hash digest
SHA256 f54f9f7e606d81ce5de9e771a7bc0e7db4615d45fdd6edeb2c54220a06554c5c
MD5 619a8f6c4d48873b2608ca40e7730635
BLAKE2b-256 e2c67142391bdc0b62f31c0f503a44280b1ce5ef1c0a636bd5dfdaec30a1f362

See more details on using hashes here.

File details

Details for the file ranglerpy-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: ranglerpy-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 25.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.17

File hashes

Hashes for ranglerpy-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6a046bb853f1c1df16c2adc44cb3849bf56f82b602e9602c7a314ae96d3824bd
MD5 575b5852050d7cd0ec43f204f306f69d
BLAKE2b-256 94c984e6cc39a0f7f0b9b2fc139114a9c34a94ce4514d1a59e5b1bcadbd33e5d

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