# Hustle > Hustle is an employee-owned text, video, and voice communications platform that lets organizations engage audiences at scale — broadcast texting, peer-to-peer 1:1 conversational texting, video messaging (Clips and Stories), and an outbound dialer. It is used by nonprofits, education, commercial businesses, political campaigns, government, and labor unions. The Hustle Public API (v3) is a RESTful, OAuth2 client-credentials interface for managing agents, groups, leads, custom fields, tags, organizations, CRM integrations, message delivery status, and webhooks. > > Generated by API Evangelist from Hustle's public developer surface. Hustle serves no /llms.txt of its own (https://hustle.com/llms.txt and https://api.hustle.com/llms.txt both 404 as of 2026-08-13). ## APIs - [Hustle Public API v3](https://api.hustle.com/v3/docs/): RESTful API for agents, groups, leads, custom fields, tags, organizations, integrations, messages, and webhook registrations. Base URL https://api.hustle.com/v3. 13 paths, 23 operations. ## Specs - [OpenAPI 3.1.0 (swagger.json)](https://api.hustle.com/v3/docs/swagger.json): The published spec for the Hustle Public API. Note: the human docs page at /v3/docs/ is a Redoc shell — this is the real machine-readable contract. - [Developer guide (prose)](https://api.hustle.com/v3/docs/description.html): Authentication, response shapes, pagination, rate limiting, best practices, and the 3.0 release notes. ## Authentication - OAuth2 client-credentials flow. POST https://api.hustle.com/v3/oauth/token with `grant_type=client_credentials`, `client_id` (email-formatted), and `client_secret` to receive a Bearer access token. Send it as `Authorization: Bearer ` on subsequent requests. - Tokens are JWTs valid for 7200 seconds (2 hours). Reuse a token until it expires; mint a new one and retry once on a 401. - No scope catalog is published. The token response carries a `scope` string (e.g. `read:account write:account`) but no enumerable scope reference exists. - No OIDC discovery and no RFC 8414 `/.well-known/oauth-authorization-server` document — the token endpoint is only discoverable from the prose docs. ## Conventions - Send request bodies as JSON, not form-encoded. Form encoding flattens nested objects and produces `[property]: Expected object, received array`. - Every response, including errors, is `application/json`. Single resources carry at least `id`, `type`, and `createdAt` (ISO 8601). - Cursor pagination: pass `cursor` and `limit`; responses return `items`, `cursor`, and `hasMore`. Default limit 100, maximum 1000. Total record counts are not available in v3. - Idempotency: POST /leads is an upsert keyed on (organizationId, phoneNumber) — 200 on update of an existing lead, 201 on create. There is no Idempotency-Key header. - Rate limits: 25 requests/second per account on resource endpoints. POST /oauth/token instead limits FAILED attempts — 10 failures blocks your IP for that account, 100 failures in 24 hours blocks the IP. No RateLimit-*/Retry-After headers are published and no 429 is declared; self-throttle. - Errors: custom JSON envelope `{ code, message, hustleErrorCode? }` — NOT RFC 9457 problem+json. `hustleErrorCode` generally appears on 422 and is what Hustle support triages on. - Webhooks: `consentUpdate-v1` and `messageStatus-v1` events, HMAC signed with a per-registration secret that the API never returns. ## Operations - Access token: POST /oauth/token - Agents: GET /agents, POST /agents, PUT /agents/{id} - Custom fields: GET /custom_fields, POST /custom_fields - Groups: GET /groups, POST /groups - Integrations: GET /integrations, POST /integrations, PATCH /integrations (PDI, VAN, VAN MyVoters, Salesforce, EveryTrue, BB Luminate) - Leads: GET /leads, POST /leads (upsert), PATCH /leads (applyTag, removeTag, setCustomField, optOut, makeActiveInGroup, makeInactiveInGroup, attachLeadToIntegration) - Messages: GET /messages/{id} (delivery status; `status` is an open string, `errorCode` present on failure) - Organizations: GET /organizations - Tags: GET /tags, POST /tags - Webhooks: GET /webhook_registrations, POST /webhook_registrations, PUT /webhook_registrations/{id}, DELETE /webhook_registrations/{id}, POST /webhook_registrations/mock_event ## SDKs - [hustle-public-api-client (Python)](https://github.com/Hustle/hustle-public-api-samples): the only first-party client, generated with openapi-python-client and shipped as source from Hustle's GitHub org — it is not on PyPI. Version v3.0.0, last commit 2024-09-04; it does not cover /messages or /webhook_registrations. - No first-party client exists on npm, PyPI, RubyGems, Maven Central, NuGet, crates.io, Packagist, or pkg.go.dev. ## Agent surface - No MCP server (no remote endpoint, no stdio package) — see mcp/hustle-mcp.yml for a derived candidate tool list. - No A2A agent card at /.well-known/agent-card.json or /.well-known/agent.json on either host. - No /.well-known documents of any kind on hustle.com or api.hustle.com. ## Docs - [API Documentation](https://api.hustle.com/v3/docs/) - [v2 API docs](https://api.hustle.com/v2/docs) and [v1 API docs](https://api.hustle.com/v1/docs) — both still live, no sunset announced - [Help Center](https://help.hustle.com/hc/en-us) - [Blog / Resources](https://hustle.com/resources/) ([RSS](https://hustle.com/feed/)) - [Security & Compliance](https://hustle.com/security/) (SOC 2, CSA STAR — [CAIQ](https://cloudsecurityalliance.org/registry/hustle-inc/)) - [Status](https://status.hustle.com/) - [Pricing / Demo](https://hustle.com/pricing/) — PAYGO $250 platform fee + $0.04/SMS segment, or annual commitment from $10,000/year - [Terms and Conditions](https://hustle.com/terms-and-conditions/) - [Acceptable Use Policy](https://hustle.com/acceptable-use-policy/) - [Privacy Policy](https://hustle.com/privacy-policy/) - [Texting compliance / 10DLC](https://hustle.com/texting-compliance/)