Skip to content

Blueprints ​

A blueprint is one JSON file that describes how an organization is set up: its custom fields, seed records, forms, webhooks, dashboard, branding and bid statuses.

Without one, setting up a new organization means clicking through Settings screen by screen, and there's no way to copy a working setup to the next customer. A blueprint makes that setup declarative, portable, and repeatable: you can preview what it would change, apply it, and export a live organization back out as one.

There is no blueprint screen in the app

Blueprints are an API capability, used by scripts, by us during onboarding, and by the AI assistant. Everything a blueprint configures is also editable in the app afterwards. The blueprint just gets you there in one step.

The four rules ​

Everything about how blueprints behave follows from these:

Merge-patch. Only what you name is touched. A blueprint containing one custom field changes that field and nothing else. It is not a full description of the org, so leaving something out never removes it.

Natural keys, never ids. A field is matched by its key, a webhook by its url, a form or customer by name. That's what makes a blueprint portable between organizations, where internal ids would mean nothing.

Removal is explicit. Nothing is deleted unless an item says archived: true. There is no "sync" that prunes whatever isn't listed.

Idempotent. Applying the same blueprint twice is safe. The second run reports everything as noop. This is what makes re-applying an updated blueprint a normal operation rather than a risk.

What a blueprint can contain ​

SectionDeclares
custom_fieldsField definitions on any record type
entitiesSeed records: customers, properties, projects, employees, subcontractors, trades, compliance docs, rates
formsFull form definitions, draft or published
webhooksOrganization-level event webhooks
form_webhooksPer-form webhooks
dashboards.orgThe organization's home dashboard
brandingApp name, logo text, colours, fonts
bid_statusesThe subcontractor bid pipeline

Plus blueprint_version (always 1) and optional name / description labels.

Unknown keys are rejected rather than ignored, so a typo fails loudly instead of silently doing nothing.

What it deliberately doesn't cover ​

Work-order types, the status registry, document templates, estimate templates, saved views, detail layouts, users, roles and API keys are not in a blueprint. They're configured in the app. Nor can you seed work orders, estimates, invoices, leads or contracts; you can define custom fields on those, but not create records.

Applying one ​

Always two steps.

1. Plan: a dry run. Returns an operation per item (create, update, noop, archive, error) plus a summary and a plan_hash. Nothing changes.

2. Apply: pass the blueprint, optionally with the plan_hash you were given.

POST /v1/blueprint/plan     scope: blueprint:read
POST /v1/blueprint/apply    scope: blueprint:apply

Both scopes must be granted explicitly on an API key. See Developer settings.

Two ways apply refuses to run:

  • Any validation error stops everything (422). Nothing is written, so a blueprint with one bad field doesn't half-configure your org.
  • A stale plan_hash (409) means the org changed between plan and apply. It is optional. Omit it and you get no such protection.

Apply is not a transaction

There's no rollback. If something fails mid-run, items already applied stay applied, the failure is reported, and anything depending on it is skipped. Fix the blueprint and apply again. That's what idempotency is for.

Archiving is not uniform ​

Worth knowing before you write archived: true:

  • Custom fields and seed records are soft-archived, so they're recoverable.
  • Webhooks and form webhooks are permanently deleted.

Exporting an organization ​

GET /v1/blueprint/export snapshots a live org into a blueprint you can apply elsewhere. Refs are reversed back to names, and internal ids, timestamps and computed values are stripped so the result is portable.

An export contains real customer data

The entities section includes every live customer, employee and subcontractor: names, emails, phone numbers, addresses. An export is a configuration and CRM dump, not just settings. Treat it like a database export: don't paste one into a ticket, a chat, or an AI tool you wouldn't hand the customer list to.

Secrets are never exported. Webhook signing secrets aren't even read from the database during export, and a newly created webhook's secret appears once in the apply result and nowhere else.

Canon fields ​

Some field definitions are marked canon, meaning they're authored and maintained by Blok rather than by your organization. The estimating cost model is the main example: roughly thirty fields on estimates and estimate lines that the billing and document code reads by name.

What that means in practice:

You canYou can't
Stop using a canon field (archive it)Rename it, retype it, or change its options
Choose whether it prints on customer-facing documentsDelete it
Add your own fields alongsideConvert one of your fields into a canon field

This is enforced in the database, not just the interface.

Archiving a canon field sticks. Re-applying the blueprint won't quietly bring it back. And your "show on documents" choice is never overwritten by a re-apply, so tuning that in the app is safe.

The trade-off: canon field ids are a contract the estimating engine depends on. Opting out of one means owning that part of the workflow yourself. It works, you're just off the paved road.

Starter templates ​

Five are shipped, available from GET /v1/blueprint/templates and browsable at blokblueprints.my-tlt-app.com:

  • Blok canon: Estimating. The canon estimating field set: header defaults, line classification, cost buildup, and formula display columns. Also the only template that seeds the bid-status pipeline.
  • Coatings subcontractor: the richest starter, modelled on a real operator: lead pipeline, coatings-specific job fields, a formula-driven sell price, a T&M rate card, four published field forms, and a dashboard.
  • Solo contractor: a lean setup: a few fields, two rates, a daily job log.
  • Crew: crew roles and certifications, daily log, timesheet and safety forms.
  • Multi-crew GC: project phases, subcontractor ratings and licences, a trades list, sub sign-in and safety audit forms.

Gotchas ​

A key can't be reused after archiving. Re-declaring an archived field's key is a hard error. Restore the old one or pick a new key.

Duplicate natural keys are fatal. Two customers with the same name make that name ambiguous, and blueprint updates for it fail until you resolve it. Same for two items sharing a key inside one blueprint.

A required custom field can block seed records. Declaring a field required and then seeding a record without a value fails that record, even if the record doesn't mention custom fields at all. The plan surfaces this before you apply.

bid_statuses replaces the whole list, rather than merging. Omitting a status removes it. (The four system statuses re-appear automatically.)

branding merges deeply. You can set a colour but not unset one.

Section order is fixed, not document order. You can reference a customer or form created in the same blueprint, but only those four types can be referenced by name at all: customers, trades, subcontractors and forms.

Updating a published form bumps its version. Past submissions keep the version they were captured under.

Internal documentation. Not for distribution.