Branding and customization

Put your logo, colors, fonts, terminology, and support links on every Wingspan screen and email your contractors see, through the V3 API.

You set branding in two places:

WhereEndpointWhat it controls
Organization customizationGET and PATCH /v3/platform/customizationCompany name, logos, the full visual theme, terminology, support links, and email branding. Every Account in your Organization uses it.
Account profilePATCH /v3/platform/accounts/{accountId}One Account's logo, brand color, and support contact. They appear on that Account's invite page and in the ACH and card authorization terms.

Organization customization covers the signed-in Wingspan app, embedded onboarding and payout screens, and Wingspan emails. Reading it needs the users.customization:read scope and updating it needs users.customization:write. PATCH follows JSON Merge Patch: fields you leave out keep their current value, and null clears a field. To change the customization of another Account's Organization, send that Account's ID in X-Wingspan-Account.

Brand identity

FieldWhat it's for
companyNameYour company name. Contractors see it where they'd otherwise see Wingspan.
websiteUrlYour company website.
logoUrlYour main logo.
secondaryLogoUrlThe logo in the app header. When it's set, the header shows it instead of logoUrl, so use the version that reads best at header height.
faviconUrlThe browser tab icon on Wingspan-hosted pages.

Logo and favicon URLs must be public HTTPS URLs. The app header has a light background, so use a dark or full-color logo there. A white (reverse) logo won't show up. If you set assetOrigin to SelfHosted, every URL must be on your own domain.

Visual theme: appearance

appearance styles every Wingspan-hosted and embedded screen: buttons, links, text fields, checkboxes, dropdowns, and text. Every key is optional. Set the global keys for a quick brand match, then set individual component keys where you need exact control. A component key you set takes priority over the value a global key fills in.

Values are CSS values sent as strings: colors (#1F6FEB, rgba(31, 111, 235, 0.4)), lengths (8px, 1rem), font stacks, shadows, and font weights ("600").

Global keys

KeyWhat it setsAlso fills in, unless you set these yourself
colorPrimaryYour primary brand colorbutton.primaryBg, button.secondaryBorder, button.secondaryColor, link.color, input.borderColorFocus, control.checkedBg, control.checkedBorder, plus the hover, pressed, and focus shades below
borderRadiusCorner roundingbutton.borderRadius, input.borderRadius, select.dropdownBorderRadius
fontFamilyFont stackbutton.fontFamily, input.fontFamily, text.fontFamily, select.searchFontFamily
colorTextText colortext.color, control.labelCheckedColor
colorBorderBorder colorinput.borderColor

Wingspan derives these shades from colorPrimary:

KeyShade
button.primaryBgHover, link.colorHover20% darker
button.primaryBgActive, link.colorActive45% darker
button.focusRingColor, input.focusRingColor, control.focusRingColor80% lighter
button.secondaryActiveBg90% lighter
button.secondaryHoverBg, control.activeBg95% lighter

Send colorPrimary as six-digit hex, such as #1F6FEB, so Wingspan can derive the shades. If you use another color format, set the hover, pressed, and focus keys yourself. The top-level primaryColor field and appearance.colorPrimary are the same setting.

button

KeyWhat it styles
borderRadiusButton corner rounding
fontFamilyButton font
fontWeightButton font weight
primaryBgPrimary button background
primaryBgHoverPrimary button background on hover
primaryBgActivePrimary button background while pressed
primaryColorPrimary button text
secondaryBorderSecondary (outline) button border
secondaryColorSecondary button text
secondaryHoverBgSecondary button background on hover
secondaryActiveBgSecondary button background while pressed
tertiaryBorderTertiary button border
tertiaryColorTertiary button text
focusRingColorFocus ring around a button
disabledBgDisabled button background
disabledColorDisabled button text

link

KeyWhat it styles
colorLink color
colorHoverLink color on hover
colorActiveLink color while pressed

input

Text fields and other form inputs.

KeyWhat it styles
borderRadiusInput corner rounding
borderColorInput border
borderColorFocusInput border while focused
bgInput background
colorInput text
placeholderColorPlaceholder text
fontFamilyInput font
focusRingColorFocus ring around an input
disabledBgDisabled input background
disabledColorDisabled input text

control

Checkboxes, radio buttons, and switches.

KeyWhat it styles
borderColorControl border
checkedBgBackground when checked
checkedBorderBorder when checked
activeBgBackground while pressed
focusRingColorFocus ring around a control
labelColorLabel text
labelCheckedColorLabel text when checked
disabledBgDisabled control background
disabledBorderDisabled control border

text

text.fontFamily and text.color set the font and color for all text. Each text style below takes fontSize, lineHeight, and fontWeight.

KeyUsed for
display1, display2Display text, largest first
heading1 to heading5Headings, largest first
paragraphBody text
paragraphSmSmall body text
paragraphXsExtra-small body text
captionCaptions and helper text

select

Dropdown menus.

KeyWhat it styles
dropdownBgMenu background
dropdownBorderRadiusMenu corner rounding
dropdownShadowMenu shadow
optionHoverBgOption background on hover
optionActiveBgBackground of the selected option
searchFontFamilyFont in the menu's search box

Fonts

Wingspan screens load the fonts you declare in fonts. Add your font there from Google Fonts or as a hosted .woff2 file, then use the same family name in appearance. End every font stack with a generic family such as sans-serif. If your font can't load, the text then falls back to a sans-serif font instead of the browser's default serif.

Examples

One color is enough to rebrand buttons, links, focus states, and checkboxes:

curl -X PATCH https://api.wingspan.app/v3/platform/customization \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "appearance": { "colorPrimary": "#1F6FEB" } }'

A full brand setup with logos, a custom font, and component overrides:

curl -X PATCH https://api.wingspan.app/v3/platform/customization \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "companyName": "Northwind Staffing",
    "websiteUrl": "https://www.example.com",
    "logoUrl": "https://www.example.com/northwind-logo.png",
    "secondaryLogoUrl": "https://www.example.com/northwind-wordmark.png",
    "faviconUrl": "https://www.example.com/favicon.png",
    "fonts": {
      "bodyFont": {
        "source": "GoogleFonts",
        "family": "Inter",
        "googleFontsFamily": "Inter",
        "fallback": "system-ui, sans-serif"
      }
    },
    "appearance": {
      "colorPrimary": "#1F6FEB",
      "borderRadius": "8px",
      "fontFamily": "Inter, system-ui, sans-serif",
      "colorText": "#111827",
      "colorBorder": "#E5E7EB",
      "button": {
        "borderRadius": "6px",
        "fontWeight": "600",
        "primaryBg": "#1F6FEB",
        "primaryBgHover": "#1959BC",
        "primaryBgActive": "#113D81",
        "primaryColor": "#FFFFFF",
        "secondaryBorder": "#1F6FEB",
        "secondaryColor": "#1F6FEB",
        "secondaryHoverBg": "#F4F8FE",
        "secondaryActiveBg": "#E9F1FD",
        "focusRingColor": "rgba(31, 111, 235, 0.4)",
        "disabledBg": "#E5E7EB",
        "disabledColor": "#9CA3AF"
      },
      "link": {
        "color": "#1F6FEB",
        "colorHover": "#1959BC",
        "colorActive": "#113D81"
      },
      "input": {
        "borderRadius": "6px",
        "borderColor": "#D1D5DB",
        "borderColorFocus": "#1F6FEB",
        "bg": "#FFFFFF",
        "color": "#111827",
        "placeholderColor": "#9CA3AF",
        "focusRingColor": "rgba(31, 111, 235, 0.4)"
      },
      "control": {
        "borderColor": "#D1D5DB",
        "checkedBg": "#1F6FEB",
        "checkedBorder": "#1F6FEB",
        "labelColor": "#374151"
      },
      "text": {
        "color": "#111827",
        "heading1": { "fontSize": "2rem", "lineHeight": "2.5rem", "fontWeight": "700" },
        "paragraph": { "fontSize": "1rem", "lineHeight": "1.5rem", "fontWeight": "400" }
      },
      "select": {
        "dropdownBg": "#FFFFFF",
        "dropdownBorderRadius": "8px",
        "dropdownShadow": "0 4px 6px rgba(0, 0, 0, 0.1)",
        "optionHoverBg": "#F3F4F6",
        "optionActiveBg": "#E5E7EB"
      }
    }
  }'

The response returns the full customization, including appearance.

CSS variables

Each appearance key sets a CSS custom property on Wingspan screens. For example, button.primaryBg sets --ws-button-primary-bg, and text.heading1.fontSize sets --ws-text-heading1-font-size. Use appearance for everything it covers, and css.variables or css.stylesheetUrl for styling outside these keys.

Terminology

Rename the words people see in the app. Keys that start with sendPayments change your team's screens. Keys that start with getPaid change what contractors see.

KeyDefaultWhere it appears
sendPaymentsContractorContractorSide navigation and page titles. The app pluralizes it, so Provider shows as "Providers".
sendPaymentsPayablePayablePayables navigation, page titles, and tables
sendPaymentsPaidAtProcessed (paid)The paid-date column in payables tables
sendPaymentsOverdueAtPast DueThe overdue status label
getPaidClientClientThe company paying the contractor
getPaidInvoiceInvoiceContractor invoices
curl -X PATCH https://api.wingspan.app/v3/platform/customization \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "terminology": {
      "sendPaymentsContractor": "Provider",
      "sendPaymentsPayable": "Work order",
      "getPaidClient": "Practice"
    }
  }'

Support links and contacts

FieldWhat it does
supportEmailYour general support email.
support.payerSupportEmailThe support email your team members see.
support.payeeSupportEmailThe support email contractors see.
support.documentation.generalUrlYour help center.
support.documentation.payoutInformationUrlYour page about how contractors get paid. Contractors see a link to it in their payout settings.
support.documentation.refundPolicyUrlYour refund policy. The international bank account form links to it.
support.portal.generalUrlYour support portal. When it's set, Support in the app opens your portal in place of Wingspan's support chat.
curl -X PATCH https://api.wingspan.app/v3/platform/customization \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "supportEmail": "[email protected]",
    "support": {
      "payerSupportEmail": "[email protected]",
      "payeeSupportEmail": "[email protected]",
      "documentation": {
        "generalUrl": "https://help.example.com",
        "payoutInformationUrl": "https://help.example.com/payouts",
        "refundPolicyUrl": "https://www.example.com/refund-policy"
      },
      "portal": { "generalUrl": "https://support.example.com" }
    }
  }'

Emails

contractorInviteMessage adds your own HTML paragraph inside every contractor invite email. Wingspan removes unsafe markup before sending.

To add a note to one invitation, send up to 2,000 characters of plain text in customMessage on Invite a payee. The message appears in the invitation email Wingspan sends.

curl -X POST https://api.wingspan.app/v3/payments/payees/Py3mQw7kLx2tRb9nVd4sHa/invite \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "customMessage": "Welcome to Northwind Staffing. Set up payments so we can pay you for your first shift." }'

Team-member invites (POST /v3/platform/persons/{personId}/invite) accept a message and a redirectUri for where the person lands after signing up.

To send Wingspan emails from your own domain, set emails.ap, emails.ar, or emails.transactional to WingspanManagedBranded with a verified senderDomain. emailTemplates overrides the subject, sender name, preview text, body, and button label of individual emails. See Update Organization branding for every option.

Account profile: logo, brand color, and support contact

Every Account also has a presentation profile. A new payee sees that Account's logo and brand color on the invite page before signing in, and supportEmail appears in the ACH and card authorization terms your customers accept. Update an Account sets these profile fields:

FieldWhat it's for
logoUrlA public URL for the Account's logo.
brandColorThe Account's brand color.
supportEmailThe business support email shown in the ACH and card authorization terms your customers accept.
supportPhoneA support phone number.
locale, timezoneThe Account's locale and time zone.

Important: profile is replaced as a whole. If you send profile, send every profile field you want to keep, not only the one you're changing. Read the Account first with GET /v3/platform/accounts/{accountId}, change the field, then send the complete object. Leaving profile out of the request leaves it unchanged.

curl -X PATCH https://api.wingspan.app/v3/platform/accounts/Ap4tYs8KqW2nLm6xRb1cVe \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "profile": {
      "logoUrl": "https://www.example.com/northwind-logo.png",
      "brandColor": "#1F6FEB",
      "supportEmail": "[email protected]",
      "supportPhone": "+1 555 010 0199",
      "locale": "en-US",
      "timezone": "America/Chicago"
    }
  }'

Reading and updating an Account needs the users.account:read and users.account:write scopes.

profile is for display only. It can also hold company.links (websiteUrl, linkedInUrl, and other social links). Omitting company keeps its links, and sending company replaces them. Don't set identity there: the legal name, address, and tax ID of record live on the Account's compliance entity. See Tax information.

Moving from V1

V1 customization (PATCH /users/customization/{id}) maps to V3 like this. appearance and terminology keep the same keys.

V1 fieldV3 field
branding.namecompanyName
branding.urlwebsiteUrl
branding.primaryLogoUrllogoUrl
branding.secondaryLogoUrlsecondaryLogoUrl
appearanceappearance
terminologyterminology
support.generalSupportEmailsupportEmail
support.payerSupportEmail, support.payeeSupportEmail, support.documentation, support.portalSame paths under support
emailCustomization.templates.contractorInvite.payerMessageSnippetcontractorInviteMessage
emailCustomization logos, footer, and styleslogoUrl, emailTemplates, and emails
inheritanceStrategy.organizationAccountConfigThe branding mode on the child's parent link (Overridable, Enforced, or Disabled). By default an Account inherits the branding values it hasn't set from its parent Accounts. See Parent and child Accounts.

Your own screens

If you want contractors to see only your product, build the screens yourself on the API. See Embed Wingspan in your app for which steps you can collect through the API and which run in Wingspan-hosted views.

Related pages


Did this page help you?