Documentation

Brand profiles

One saved brand per contractor you order for: company name, contact block, license #, colours, logo and a contact. Named as brand when placing an order.

API reference

Base URL: https://api.roofquery.com. Authenticate with Authorization: Bearer <your key> — except the file routes (report and storm report files), which take no key.

Copies this whole page as Markdown, so you can paste it into an assistant and have it write the integration. Nothing secret goes on the clipboard — your keys aren't included.

Brand profiles

A profile is one contractor you order for: a company name, a contact block, a license number, two colours and a logo. Name it as brand when you place an order, and that order's PDF carries the contractor's brand, logo included, for good. The profile's contact email and phone are never printed: they're who we reach if we need more information about the property. Nothing about your own account defaults changes.

MethodPathDescription
GET/api/v1/branding/profilesEvery profile on the account, newest first
POST/api/v1/branding/profilesCreate. Returns 201 with the profile and its id
GET/api/v1/branding/profiles/:idOne profile
PATCH/api/v1/branding/profiles/:idChange any text or colour field. Omitted fields are left alone
DELETE/api/v1/branding/profiles/:idDelete the profile and its logo file. A profile that orders were placed for can't be deleted: 409 BRAND_IN_USE (edit it instead)
PUT/api/v1/branding/profiles/:id/logoUpload the logo: raw image bytes as the body, with an image Content-Type
DELETE/api/v1/branding/profiles/:id/logoRemove the logo. The rest of the profile stays
Parameters

The JSON body of POST and PATCH.

FieldRequiredDescription
companyNameTo createPrints on the header band, footer and cover attribution, and is how the profile is listed. 80 chars
licenseNumberNoContact block, as License # …. 40 chars
contactEmailNoNever printed. Who we email about a property. 160 chars
contactPhoneNoNever printed. Who we call about a property. 32 chars
addressNoContact block. 160 chars
publicPhoneNoContact block. 32 chars. A 10-digit number is formatted (502) 555-0100
publicEmailNoContact block. 160 chars
brandColorNoHex. Defaults to RoofQuery blue
brandTextColorNoHex. Picked for contrast when omitted

With no contact on the profile, we reach your own account's contact instead; an order is never refused for it.

Request
curl -X POST "https://api.roofquery.com/api/v1/branding/profiles" \
  -H "Authorization: Bearer rq_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "companyName": "Acme Roofing",
    "address": "900 Bardstown Rd, Louisville, KY 40204",
    "publicPhone": "5025559876",
    "publicEmail": "[email protected]",
    "licenseNumber": "KY-RC-48213",
    "contactEmail": "[email protected]",
    "contactPhone": "5025550142",
    "brandColor": "#0F7A4D"
  }'
Response
HTTP/1.1 201 Created

{
  "profile": {
    "profileId": "rq_brand_7f3a21c9d4e07b16",
    "companyName": "Acme Roofing",
    "address": "900 Bardstown Rd, Louisville, KY 40204",
    "publicPhone": "5025559876",
    "publicEmail": "[email protected]",
    "licenseNumber": "KY-RC-48213",
    "contactEmail": "[email protected]",
    "contactPhone": "5025550142",
    "brandColor": "#0F7A4D",
    "brandTextColor": null,
    "hasLogo": false,
    "createdAt": "2026-09-09T14:02:11.000Z",
    "updatedAt": "2026-09-09T14:02:11.000Z"
  }
}

Then the logo, as bytes. No multipart, no JSON wrapper — the file is the body:

curl -X PUT "https://api.roofquery.com/api/v1/branding/profiles/rq_brand_7f3a21c9d4e07b16/logo" \
  -H "Authorization: Bearer rq_live_sk_..." \
  -H "Content-Type: image/png" \
  --data-binary @acme-logo.png

And then order for that contractor with "brand": "rq_brand_7f3a21c9d4e07b16". Every PDF of that order carries Acme Roofing.

A profile is complete. Every printed field comes from the profile and nothing falls through to your account defaults — a profile with no phone number prints no phone number, rather than yours under the contractor's name. The PDF is drawn when it's downloaded, so editing a profile updates the reports ordered for it.

Orders placed before 22 October 2026 don't have a brand of their own: they still take one on a download link as ?brand=<profileId>, checked against the company that placed the order (an unknown or foreign id is 404 not_found, like an unknown order id). See White labeling. Ids are rq_brand_ plus 64 random bits.

Logos go through the same pipeline as your account logo: PNG, JPEG, WebP, GIF, AVIF or SVG, under 5MB, squared to a 512×512 PNG with transparent padding. There is no URL field, on purpose — see White labeling. Up to 500 profiles per account; past that, 409 profile_limit. Profiles can also be created and edited by hand in the portal under Branding → Profiles, which shows each one's id and a test PDF.

Errors

validation (400), not_found (404), profile_limit and BRAND_IN_USE (409), and for logos empty_upload (400), too_large (413, over 5MB), payload_too_large (413, a body over 6MB), unsupported_type (415) and unreadable_image (422). Every code is under Errors.