Skip to main content
HoundDog API Documentation

Migrating from v1

v1 keeps working unchanged alongside v2, with the same API keys; no sunset date is set.

Every response from a v1 endpoint carries two headers that mark it as deprecated: Deprecation: @1798761600 (2027-01-01, the date v1 is deprecated from, in the date form of RFC 9745: @ and Unix seconds; v1 keeps working after it) and a Link header with rel="deprecation" pointing at this page. Their bodies and status codes are unchanged, and no Sunset header is sent. Clients that log or alert on these headers can use them to find any v1 calls left in their code.

Every v1 endpoint and its v2 page

v1 v2 Page
GET /api/v1/vendors GET /api/v2/parties (enveloped, see Pagination) Parties
GET /api/v1/vendors/:id GET /api/v2/parties/:id Parties
GET /api/v1/vendors/external_id/:external_id GET /api/v2/parties?external_id=<value> (a collection; empty when nothing matches) Parties
POST /api/v1/vendors/create (form-encoded) POST /api/v2/parties (JSON body) Parties
GET /api/v1/certificates GET /api/v2/certificates Certificates
GET /api/v1/certificates/:id GET /api/v2/certificates/:id, which also returns the parsed coverage data; the file is at GET /api/v2/certificates/:id/download Certificates
GET /api/v1/documents GET /api/v2/documents Documents
GET /api/v1/documents/vendor/:id GET /api/v2/parties/:id/documents Documents
GET /api/v1/documents/:id GET /api/v2/documents/:id Documents
POST /api/v1/documents/create POST /api/v2/documents Documents
GET /api/v1/events GET /api/v2/events (with filters and the since_id cursor) Events
GET /api/v1/events/:id GET /api/v2/events/:id Events
GET /api/v1/insurance_requirements GET /api/v2/insurance_requirements Insurance requirements
GET /api/v1/insurance_requirements/:id GET /api/v2/insurance_requirements/:id Insurance requirements
GET /api/v1/projects GET /api/v2/projects Projects
GET /api/v1/projects/:id GET /api/v2/projects/:id Projects

Every /create path in v1 becomes a POST to the collection in v2. Authenticated requests to /api/v2/vendors answer 404 with a pointer here.

Names and shapes that change

List pagination changes too: v2 lists page with page and per_page only, with a larger default and cap, and have no offset parameter (see Pagination).

v1 v2
vendors (path) parties
vendor_id in payloads party_id
compliant and in_review on a vendor status.compliant and status.in_review, alongside the other state flags (manually_compliant, unresponsive, no_requirements, archived, paused, ...)
insurance_requirement_id and compliance_profile on a vendor requirements.insurance_requirement_id and requirements.compliance_profile
a vendor's projects: [{ "id", "name" }] projects: [{ "project_id", "name", ... }] with the per-project requirement and status
an event's nested vendor and user objects party_id and user_id; each event also carries its id and created_at
a project's nested insurance_requirement object insurance_requirement_id
document_file in a document file_url, a short-lived link
email on vendor create email_address
document_file (document create) file
GET /events?user_id= GET /events?user_id= (kept)
collect_compliance_on started_in_compliance: true with manual_expiration_date; in v1 the field had no effect on its own
project_ids as a comma-separated string projects: [{ "project_id": 1 }, ...] with optional per-project requirement and profile
insurance_requirement_id omitted same default behavior: the account's default requirement (or default compliance profile)
Vendor Added event for API-created parties Party Added, the same event the dashboard records
offset on list requests (answered with X-Offset and X-Prev-Page headers, neither of which v2 sends) no offset: page with page and per_page, see Pagination
per_page default 20, maximum 50 per_page default 50, maximum 200 (50 when include=detail is requested); above the cap is a 400
Bare JSON arrays { "data": [...], "total", "has_more", "next_page" }
{"error": "..."} {"error": {"code", "message", "request_id", "details"}}, see Errors
400 "Malformed Request" for almost everything precise 400 / 401 / 403 / 404 / 409 / 422 / 429 codes
Certificate payload with the file reference only the parsed coverage data once the certificate is processed, in one coverages map keyed by coverage prefix; the file through a download link
Requirement coverage fields as flat {prefix}_{field} keys (gl_per_occurance_minimum) one coverages map nested by prefix: {prefix}_{field} becomes coverages.<prefix>.<field>, the prefix removed and the rest of the name kept as is. So gl_per_occurance_minimum is coverages.gl.per_occurance_minimum and wc_employers_liability_each_accident_minimum is coverages.wc.employers_liability_each_accident_minimum; see Insurance requirements
Webhook payload {event, payload: {vendor_id, ...}} v2 subscriptions receive the signed payload on the Webhooks page; existing subscriptions are unchanged

New in v2

Everything v1 could not do: update parties, the party actions (archive, pause, reminders, certificate invalidation), contacts, certificate upload, approval overrides, compliance requests, requirement management, webhook management, account settings and users. Project management, including attaching parties. Compliance profiles. W-9s. Document signing. Requirement statuses and idempotency keys.

What does not change

  • Your API key works for both versions; no re-keying. A key's scope applies to both: a key created with the read scope cannot make v1 writes either (403).
  • Event type strings are the same in both versions and in webhooks.
  • Ids are the same integers; a v1 vendor id is a v2 party id. The lists are not the same set: v1 GET /vendors returned every party (archived, paused and incomplete ones too); v2 GET /parties defaults to lifecycle[]=active (for everything send every lifecycle value: lifecycle[]=active&lifecycle[]=paused&lifecycle[]=incomplete&lifecycle[]=archived&lifecycle[]=jobtread_archived).
  • v1 GET /certificates returned every certificate row; v2 GET /certificates leaves out documents moved to a party's insurance documents and tax forms uploaded as certificates (see Certificates).
  • v1 GET /vendors also returned your individuals; v2 never serves them, and their ids answer 404.

Requests to /api/v2/vendors

v2 has no vendors alias. An authenticated request to /api/v2/vendors answers 404 with a message pointing here; a request with no key or an invalid key gets 401, and a deactivated or API-disabled account 403, as for every other route.