APISign in

EngageCycle API

Base address: https://app.engagecycle.com/api/v1. Send Authorization: Bearer <your API key> with every request. Keys are made by owners in Integrations, API keys. Events sent to your webhook, and how to check their signature, are in Webhooks.

Not covered yet: agreements and consents sent on their own, and walkthroughs. Their webhook events are sent as usual.

The API lets your own tools (n8n, Zapier, a script) do what your team does in EngageCycle: keep clients and the catalog up to date, make proposals, preview them, and send them, and follow what happens to them. Every endpoint is listed in the reference below this guide, and the machine-readable description is /api/v1/openapi.json (OpenAPI 3.1, readable without a key). Each operation in it carries its scope as x-scope (null for any key).

Authentication

Every request carries your API key:

Authorization: Bearer <your API key>

An owner makes keys in Integrations, API keys. A key is shown once, when it's made; EngageCycle keeps only a fingerprint of it. Turn a key off there as soon as you stop using it. The base address is https://app.engagecycle.com/api/v1.

Scopes

A key can do only what was ticked when it was made. Keys made before scopes existed have full access and are labelled "Full access (legacy)"; make a new key to narrow one.

Scope What it allows
clients:read Read clients
clients:write Add, change, archive, restore, and import clients; set who must sign; add, change, and remove a client's people
proposals:read Read proposals, previews, and signed PDFs
proposals:write Make and change drafts, preview, revise, remove a copied person's access, record handoffs and bookings
proposals:send Send, resend, and withdraw proposals, extend their deadlines, and send a copied person their copy again
proposals:links Read a client's signing link, and the links inside events from GET /events (each read is in the activity log)
catalog:read Read the catalog, templates, and presets
catalog:write Add and change catalog items, but not their prices
catalog:prices Set and change catalog prices (with catalog:write)
campaigns:read Read campaigns
offers:read Read offers and their leads
events:read Read events
events:write Send an event to your webhook again
documents:read Read agreements, consents, and their signed PDFs, and their document.* events from GET /events

GET /me and GET /credits work with any key. A missing scope is 403 missing_scope, and the error's scope names the one needed. Two routes need a second scope only for part of what they do: setting or changing a price on POST /catalog or PATCH /catalog/{id} needs catalog:prices as well as catalog:write, and GET /events with a document.* type needs documents:read as well as events:read.

Money, times, and ids

  • Money is a whole number of the smallest unit of your business's currency (cents for USD), with the currency beside it: 45000 with USD is $450.00. unit_cents: null means no price has been set yet, which is different from 0 (shown to clients as "Included").
  • Times are ISO 8601 in UTC, like 2026-10-08T14:30:00.000Z.
  • Ids are UUIDs. Event ids are evt_ followed by 32 hexadecimal characters, the same as the webhook's.

Lists and pages

Lists answer { "data": [...], "next_cursor": "..." }. Ask for up to 200 at a time with ?limit= (50 if you don't say), and pass next_cursor back as ?cursor= for the next page. next_cursor is null on the last page. A cursor is a position, not a page number, so a page never repeats or skips anything when new records arrive while you're reading. Lists are newest first, except events.

Leads and prospects

GET /leads (scope offers:read) lists the people who started one of your offers. A lead's status is one of started (hasn't confirmed their email), verified (confirmed, with a proposal), signed, abandoned, discarded, converted_existing (sent to a proposal they already had), and, on an offer that holds requests for review, awaiting_review, declined_by_business, and review_expired. Filter with ?status=, ?offer_id=, or ?created_since=.

Someone who confirms their email on an offer isn't one of your clients until they sign (or you add them): GET /clients leaves them out, and GET /clients/{id} answers 404 for them. A lead's client_id names their record either way. POST /clients with a prospect's email adds a separate client and leaves the prospect as they are; they become a client when they sign.

One email can belong to more than one client (decided 2026-10-24): a person and their business often share one. POST /clients with an email already in use still adds the client, and its answer's email_shared_with lists the other clients' ids (empty when none). GET /clients?email= returns every client with that email. Imports match by email only when exactly one client has it; a row without an external_id whose email more than one client uses is refused with "More than one client uses this email. Add an ID column to say which one."

Idempotency

Send an Idempotency-Key header (any unique text up to 200 characters, for example the n8n execution id plus a step name) when you create or send something. It's required on:

  • POST /clients
  • POST /clients/{id}/people
  • POST /catalog
  • POST /proposals
  • POST /proposals/{id}/send
  • POST /proposals/{id}/resend
  • POST /proposals/{id}/extend
  • POST /proposals/{id}/revise
  • POST /proposals/{id}/copied/{personId}/resend

and accepted on every other POST, PATCH, and DELETE. If the same request arrives again with the same key within 24 hours, you get the first answer back, with the header Idempotent-Replayed: true, and nothing is done twice: a retried send never sends a second time. That includes an error: a request refused with a key is refused again with that key, so use a new key once you have fixed the cause. The same key with a different request is 422 idempotency_key_reused; a key whose first request is still running is 409 idempotency_in_progress.

Errors

Every error has the same shape:

{ "error": { "code": "preview_changed", "message": "This changed since your preview. Preview it again.", "field": "build.packages.0.items.1.qty" } }

Branch on code; message is written for a person, and field (when present) names the input at fault. A few codes add one more field: missing_scope has scope, unknown_columns has columns, and internal_error has request_id.

Status Codes What happened
400 invalid_body, invalid_query, validation Something in the request isn't right; see field and details
400 sensitive_value A value looks like a Social Security number, ITIN, or EIN. EngageCycle never stores government ID numbers
400 idempotency_key_required This request needs an Idempotency-Key
401 unauthorized No key, or a key that's wrong or turned off
402 out_of_credits Sending needs a credit and there's none left
403 missing_scope The key doesn't have the scope this needs
403 not_on_plan Your plan doesn't include the API
403 forbidden Your plan doesn't include what this needs (Multiple signers, or Agreement and Consent for documents)
403 paused, closed The business is paused or closed: reading still works, changes are refused
403 deleted The business is being deleted: nothing works
404 not_found No such record in your business
404 no_open_proposal POST /bookings/match: that email has no open proposal
409 invalid_state It can't be done now (for example, changing a proposal that was already sent)
409 idempotency_in_progress A request with this Idempotency-Key is still running
409 not_previewed, preview_changed, preview_stale Send needs a fresh preview; see below
409 send_blocked Email is paused, or your email sender isn't ready
409 conflict Something else is already using that name or id
409 webhook_off Your webhook isn't on, so an event can't be resent
409 pdf_not_ready, not_signed The signed PDF isn't there yet
413 too_large, too_many_rows The request is too big: over 1 MB (10 MB for /clients/batch and /clients/import), or over 5,000 rows in an import
422 unknown_columns An import has a column no client field takes; columns lists them
422 idempotency_key_reused This Idempotency-Key was used for a different request
429 rate_limited Too many requests; wait Retry-After seconds
500 internal_error Something went wrong on our side; request_id helps support find it

Rate limits

Each key may make 120 requests a minute. Every answer carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (when the minute ends, in Unix seconds). Over the limit you get 429 rate_limited with Retry-After.

Sending a proposal

A proposal goes out in three steps, the same as in the admin:

  1. Make a draft: POST /proposals with a client_id, and either a preset_id (a preset, from Catalog > Presets) or a build. Without a template_id it uses your default template. On 2026-10-24 /presets and preset_id replaced the address /saved-builds and the field saved_build_id, which now answer 404 and invalid_body.
  2. Preview it: POST /proposals/{id}/preview. This freezes exactly what the client will see, fixes the respond-by date, and returns preview_sha256. You can look at the document at document_url (with your key).
  3. Send it: POST /proposals/{id}/send with that preview_sha256 and email: true (EngageCycle emails the link) or email: false (the link is made and nothing is emailed; read it with GET /proposals/{id}/link, which needs proposals:links).

Send refuses with not_previewed when there's no preview, preview_changed when the draft, template, branding, or client changed since the preview, and preview_stale when the preview is from an earlier day (or over 24 hours old): preview again and send the new hash. Sending uses one credit; the answer says how many are left.

Resending the link: POST /proposals/{id}/resend (proposals:send, with an Idempotency-Key) does what Resend does in the admin. The client gets a new link, emailed when you have an email sender (otherwise proposal.sent with is_resend: true tells your automation), and their earlier links stop working. An expired proposal reopens only within 30 days of its deadline: its deadline is extended first (to expiry_days from today, logged with the reason "Sent a new link", with its own proposal.deadline_extended event), and the respond-by date the document printed doesn't change. Changed 2026-10-16: Resend used to reopen an expired proposal of any age, and moved the printed date on a campaign's proposal. Now one that ended more than 30 days ago is refused (409 invalid_state, "This ended more than 30 days ago. Start a new one to send it again."), as is a withdrawn one, which stays withdrawn. The answer never holds the link.

Extending the deadline: POST /proposals/{id}/extend (proposals:send, with an Idempotency-Key) gives the client more time on the same proposal. The link they have keeps working, and the document (and its PDF) keeps the respond-by date it printed. The body:

{ "expires_on": "2026-11-20", "reason": "Waiting on documents", "notify_client": true }
  • expires_on is a date in your business's time zone; the deadline is the end of that day. It must be later than the current deadline, not in the past, and at most 180 days from today. Otherwise it's 422 validation ("Pick a date after November 5, 2026.", "Pick a date within 180 days (by April 14, 2027).").
  • reason (optional, up to 500 characters) is for your team: it's in the activity and the event, never shown to the client.
  • notify_client (default true) emails the client (and each other signer whose turn it is) a second link with the new date. Both links work. No credit is used.
  • An open proposal can be extended any time before its deadline. An expired one can be within 30 days of its deadline, which reopens it (reopened: true). A draft, a signed, declined, withdrawn, or replaced proposal, one that ended more than 30 days ago, or one in a walkthrough is 409 invalid_state (extend a walkthrough from its page in EngageCycle).
  • The answer is the proposal (its expires_at is now the new deadline, and original_expires_at the printed date), reopened, and emailed. It writes proposal.deadline_extended (Webhooks). The answer never holds a link.

expires_at is the effective deadline. Since 2026-10-16 a proposal's expires_at (in the API and every event) is when it really ends, after any extension. An extended proposal also has original_expires_at, the respond-by date its document printed; a proposal that was never extended has no original_expires_at key at all. Documents (GET /documents/{id}) work the same way.

A build in a request is a short form. Packages list catalog items by id (copied as the builder copies them, with an optional unit_cents for this proposal only) or typed items with a name and price. Add-ons name a catalog item or have a name and price, and only_with lists the packages they go with by position (0 is the first). A typed item or add-on takes a billing (one_time, yearly, semiannual, quarterly, monthly, or weekly), and "billed_as_used": true makes it a rate: a price per unit with no quantity, never in a total. Any item or add-on takes a unit_label (free text, up to 40 characters: "form", "hour") and an optional unit_plural (when adding "s" reads wrong: "entities"); a catalog item can be given its own unit for this proposal without changing the catalog. A rate needs a unit: the draft saves without one, and preview refuses until it has one (the build lists them in no_unit). A catalog item keeps its own billing:

{
  "client_id": "6f1c...",
  "build": {
    "mode": "choose",
    "packages": [
      { "name": "Standard", "items": [{ "catalog_item_id": "3a9e..." }] },
      {
        "name": "Premium",
        "badge": "Recommended",
        "items": [{ "catalog_item_id": "3a9e..." }, { "name": "Planning call", "unit_cents": 15000 }]
      }
    ],
    "addons": [{ "catalog_item_id": "77b0...", "kind": "quantity", "max_qty": 5, "only_with": [1] }]
  }
}

mode: "fixed" is one price to approve and has exactly one package. Nothing is ever chosen for the client: packages start unselected and add-ons at their minimum.

Totals by billing frequency. Each package in a draft or preview, each preset (GET /presets), and each signature has totals: [{ "billing", "cents" }], a one-time total and then each recurring frequency on its own (yearly, semiannual, quarterly, monthly, weekly), never added together. total_cents (one-time plus yearly) and monthly_cents are kept for compatibility only; amounts billed every six months, quarterly, or weekly are only in totals, so new integrations should read totals. Lines that are rates have billed_as_used: true, with qty and amount_cents of 0. The proposal.signed webhook event carries the same totals.

Discount lines (read-only for now). A proposal can carry discount lines, added in the builder or by a campaign: fixed amounts taken off whatever the client chooses, each in one billing frequency. Over the API they can be read but not set:

  • A draft's or preview's build lists them in discounts (id, discount_id or null for a one-off, kind, label, amount_cents (positive, taken off), and billing), and each package gains net_totals: that package alone, net of them. Without discounts neither key is there.
  • A signature's totals, total_cents, and monthly_cents are what the client agreed to pay, net of discounts. With a discount the signature also has discounts (each line with its kind) and listed_totals (before them), as in proposal.signed (Webhooks).
  • A build with a discounts key is refused (400 validation: "Discounts can't be set through the API yet. Add them in the builder.").
  • A PATCH whose build replaces a draft's packages and add-ons keeps the draft's discounts. It's refused (400 validation, "A total can't go below zero") when the new packages would leave a total below zero.
  • MCP's get_proposal and preview_proposal show the same; create_proposal can't add discounts.

Business clients

A client is an individual or a business. A business is an entity, such as a company or a partnership, and a person signs for it.

  • Fields: clients carry type (individual or business; every client nobody marked reads as individual), contact_name (at most 120 characters), and contact_title (at most 80). On a business, display_name is the business's name, contact_name is the person you deal with ("Dana Lee"), contact_title is their title ("Managing Member", the prefill when they sign), and first_name is the contact's first name, filled from contact_name when you leave it out. There's no separate business name input and no ID number field of any kind.
  • Setting them: POST /clients and PATCH /clients/{id} take type, contact_name, and contact_title. Contact fields on an individual are refused with 400 validation ("contact_name is only for business clients"). Changing a business to individual removes its contact and title. Searching clients matches the contact name too.
  • Imports: POST /clients/batch and /clients/import take the columns client_type ("Individual" or "Business", any case; also "Person", "Personal", "Company", "Entity", "Organization"), business_name, contact_name, and contact_title. A row with a business_name is a business named for it; with no contact_name, its display_name is the contact. An individual's row with a contact or title still imports, with a warning ("Contact and title are only kept for business clients"). A column a file leaves out keeps the client's value, and a row whose client_type and business_name are both blank keeps the client's type and contact.
  • People: a person on a client has an optional title (at most 80), their title at the business. It's kept on an individual's people too, but used only on a business.
  • Signed for a business: on a proposal or document whose client was a business when it was sent, the signer types their title, and GET /proposals/{id} and GET /documents/{id} show the signature's signer_title ("Managing Member") and on_behalf_of (the business's name). With several signers, each entry in signers has signer_title and on_behalf_of once that signer signed, and a proposal's signers also have title, the title staff entered for them (the prefill). The proposal's client block has type: "business", contact_name, and contact_title, as the webhook events do (Webhooks). All of these are absent for an individual, never null.
  • Signed for a represented client: an individual client can have a representative (name, email, optional phone, and capacity: power_of_attorney, guardian, executor, or personal_representative), set on POST /clients and PATCH /clients/{id} (null removes it; refused on a business with 400). Everything for the client is sent to the representative, and the client's own email becomes optional. GET /clients/{id} shows it (absent when the client signs for themselves). Once the representative signs, GET /proposals/{id} and GET /documents/{id} show the signature's signer_capacity and on_behalf_of (the client's name), and that signer's entry in signers has them too. The proposal's client block has representative, as the webhook events do. All absent otherwise. Changing or removing a representative affects only what's sent afterwards.
  • MCP's create_client and update_client take the same fields; get_client and search_clients return them.

Copied people

A client can have people who are copied on their proposals: a spouse, a family member, an assistant. A copied person gets a view-only link when the proposal is sent and, unless you turn it off, the signed copy. They can never choose, sign, or decline.

  • On the client: GET /clients/{id}/people lists them; POST /clients/{id}/people adds one, PATCH /clients/{id}/people/{personId} changes one, and DELETE /clients/{id}/people/{personId} stops copying them (clients:write). A person is { "name", "email", "phone", "title", "relationship", "role" }, where relationship is spouse, family, assistant, business_partner, or other, and role is copied, or signer when the business has Multiple signers (see below; refused with 400 otherwise).
  • The client asked. Adding someone, or changing their email, needs "client_asked": true: the client asked you to share their proposals with this person. It's recorded with your key and the time. Sharing is your decision and responsibility.
  • On a draft: a new draft starts with the client's people. copied_people on POST /proposals or PATCH /proposals/{id} is the whole list for that proposal only (people already on it, matched by email, stay as they are; anyone new needs client_asked; anyone left out is removed), and copied_signed_copy: false keeps the signed copy from them. Changing only these keeps the preview. Once sent, who's copied can't change.
  • Sending: email: true emails copied people their view-only link too. With email: false, they're still emailed unless you send "email_copied": false.
  • Reading: GET /proposals/{id} has copied_people, each with link_sent_at, first_viewed_at, last_viewed_at, view_count, and access_removed_at. The webhook's proposal.sent lists them with their view_url while it's active (with proposals:links in GET /events), and proposal.copy_viewed fires the first time each one looks (Webhooks).
  • Send copy again: POST /proposals/{id}/copied/{personId}/resend (proposals:send, with an Idempotency-Key) emails them their link again: the same link while the proposal is open, otherwise a new one (their earlier link stops; new_link says which). It needs your email sender and is refused while email is paused.
  • Remove access: POST /proposals/{id}/copied/{personId}/remove-access (proposals:write). Their link says "This link is no longer active", for good, and nothing more is emailed to them. Send their copy again to give them a new link.

Several signers

When the business has Multiple signers on its plan (off on every plan unless EngageCycle turns it on), a proposal can need more than one signature, for example both spouses on a joint return. Each signer signs the same proposal with their own link. With the feature off, everything here is refused ("Multiple signers aren't on your plan."): signing on a draft and a client's default with 403 forbidden, and a person with role: "signer" with 400 validation.

  • Who signs: people with role: "signer" on the client (/clients/{id}/people) or in a draft's copied_people. At most 4 signers, the client included.
  • Who must sign: signing: { "rule": "all" | "any", "order": "any" | "in_order" } on POST /proposals or PATCH /proposals/{id} (null goes back to the client's default); POST /clients/{id}/signing { "rule" } sets the client's default, and clients carry signing_rule. The order applies to All signers only.
  • Sending: with email: true every signer whose turn it is gets their own link by email (In order, the next one when the one before signs). With email: false every link is made and nobody is emailed. The signing link the API reads is the client's own.
  • Reading: GET /proposals/{id} (and the answers to create and update) has signing and signers: [{ "name", "email", "position", "client", "state", "signed_at", "declined_at" }] (and, for a business client, title, signer_title, and on_behalf_of; see Business clients); state is waiting, open, signed, declined, or voided (a revised or withdrawn version). With one signer signing is null and signers is empty. A proposal's status is signed only once everyone needed has signed, and its signature is the agreement: the choice and signing of the signer who chose. The webhook events are in Webhooks.
{
  "client_id": "6f1c...",
  "copied_people": [
    { "name": "Sam Lin", "email": "[email protected]", "relationship": "family", "client_asked": true }
  ]
}

Documents: agreements and consents (read-only)

A business can send an agreement (an engagement letter, for example) or a consent on its own, with no price. The API reads them; making and sending one over the API is later. Every route needs the documents:read scope (a key made before scopes, with full access, has it) and Agreement or Consent on the business's plan, else 403 forbidden ("Agreement and Consent templates aren't on your plan.").

  • GET /documents: newest first, never a draft and never a proposal. Filters: kind (agreement or consent), status, client_id, since (changed since). Pages like every list.
  • GET /documents/{id}: id, kind, version, status, template (id, name), client (id, external_id, display_name), campaign_id, supersedes_id, sent_at, expires_at, resolved_at, created_at, updated_at, signers (position, client, name, state, signed_at, declined_at; empty with one signer), signature once signed (signed_at, typed_name, signing_method, and the consent documents agreed, consents; signer_title and on_behalf_of when it was signed for a business), and pdf_ready.
  • GET /documents/{id}/pdf: the signed PDF with its certificate, X-EngageCycle-Sha256 its hash; 409 not_signed or pdf_not_ready otherwise.

Nothing here returns a signing link or anyone's email. The proposal endpoints never show a document: GET /proposals leaves them out, and GET /proposals/{id}, its PDF, handoff, booked, and extend answer 404 for a document's id (extend a document from its page in EngageCycle). Their webhook events are document.* (Webhooks), and GET /events returns them only when you name them in type, with a key that has documents:read as well as events:read. MCP has no document tools yet.

Recipe: n8n, from a new client to a sent proposal

This workflow takes a name and email (from a form, a CRM, or a webhook), finds or adds the client, makes a proposal from a preset, previews it, and sends it. In n8n, make an HTTP Header Auth credential named "EngageCycle" with the name Authorization and the value Bearer <your API key> (scopes: clients:read, clients:write, catalog:read, proposals:write, proposals:send). Every HTTP Request node below uses it, with the base address https://app.engagecycle.com/api/v1.

  1. Find the client. HTTP Request, GET /clients, query email = {{ $json.email }}.
  2. IF {{ $json.data.length }} is 0, go to step 3. If it's 1, use {{ $json.data[0].id }} as the client id and skip to step 4. More than one means several clients share the email (a person and their business, say): stop and pick by hand, or find the client by external_id instead.
  3. Add the client. HTTP Request, POST /clients, header Idempotency-Key = {{ $execution.id }}-client, JSON body:
    { "display_name": "{{ $('Trigger').item.json.name }}", "email": "{{ $('Trigger').item.json.email }}" }
    
    The answer is the client; its id is {{ $json.id }}.
  4. Pick the preset once. Call GET /presets yourself, copy the id of the preset you want, and keep it in the workflow (a Set node, preset_id).
  5. Make the draft. HTTP Request, POST /proposals, header Idempotency-Key = {{ $execution.id }}-draft, body { "client_id": "<client id from step 2 or 3>", "preset_id": "<from step 4>" }. Its id is {{ $json.proposal.id }}.
  6. Preview. HTTP Request, POST /proposals/{{ $json.proposal.id }}/preview. Keep {{ $json.preview_sha256 }}.
  7. Send. HTTP Request, POST /proposals/<id>/send, header Idempotency-Key = {{ $execution.id }}-send, body { "preview_sha256": "{{ $json.preview_sha256 }}", "email": true }. If n8n retries the node, the key makes sure the client gets one email.

Turn on "Retry On Fail" for steps 3 to 7: with the idempotency keys, a retry after a timeout is safe. For a 409 preview_changed, go back to step 6. For 402 out_of_credits, stop and tell an owner.

Recipe: polling events instead of a webhook

GET /events lists every event your business records, oldest first, in exactly the shape the webhook sends (id, type, created_at, tenant, data). It's for tools that can't receive webhooks, or as a safety net beside them.

  1. Call GET /events?limit=200 once and keep next_cursor.
  2. Every few minutes (an n8n Schedule Trigger), call GET /events?since=<the cursor you kept>&limit=200, handle each event, and keep the new next_cursor. When nothing happened, data is empty and next_cursor stays the same.
  3. Repeat. Filter with type=proposal.signed (repeat type for several) or proposal_id=.

An event appears only once everything written before it is finished, so polling never skips one, even when two things happen at the same moment. Usually that is within a second; while a long job is still saving (a large campaign batch, for example), newer events wait until it finishes, and then all arrive in order. Store the event id if you also take the webhook: the same id arrives both ways. Signing links inside proposal.sent and lead.abandoned (signing_url, resume_url) come back as null (with "redacted": true) unless the key has proposals:links. Even then a link is given only while it still works: once the proposal is signed, declined, withdrawn, replaced, or expired, or a newer link was sent, it is null, the same as in the webhook. EngageCycle never keeps the link itself in an event. Each item also says how the webhook delivery went (delivery: delivered, due, failed, or off when it was recorded while the webhook was off), and POST /events/{id}/redeliver (scope events:write) sends one to your webhook again while the webhook is on.

The signed PDF for a proposal.signed event is at data.pdf.url (or GET /proposals/{id}/pdf), and needs your key.

AI assistants (MCP)

The same keys also work with EngageCycle's MCP server, POST https://app.engagecycle.com/mcp, so AI assistants such as Claude and ChatGPT can look up clients and proposals, make drafts, and send them after a preview. It counts against the same 120 requests a minute per key, needs the same scopes, and never returns signing links, even to a key with proposals:links. MCP lists each tool with the scope it needs and has setup you can copy; Integrations, MCP has the same in EngageCycle.

Reference

Account

GET /me

The business and this key

Any key.

Answer 200

Me

GET /credits

Credits left

One credit is one proposal reaching a client for the first time.

Any key.

Answer 200

Credits

Templates and presets

GET /templates

List templates proposals can use

Published Proposal templates without prices of their own, newest first.

Scope: catalog:read.

ParameterInRequiredAbout
limitquerynoHow many to return, 1 to 200
cursorquerynoThe next_cursor from the previous page

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Template"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

GET /presets

List presets

Presets: saved sets of services, packages, add-ons, and prices to start a proposal from (preset_id on POST /proposals).

Scope: catalog:read.

ParameterInRequiredAbout
limitquerynoHow many to return, 1 to 200
cursorquerynoThe next_cursor from the previous page
archivedquerynoOne of true, false

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Preset"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

Campaigns and offers

GET /campaigns

List campaigns

Scope: campaigns:read.

ParameterInRequiredAbout
limitquerynoHow many to return, 1 to 200
cursorquerynoThe next_cursor from the previous page

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Campaign"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

GET /campaigns/{id}

Get a campaign with its counts

Scope: campaigns:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

Campaign

GET /offers

List offers

Scope: offers:read.

ParameterInRequiredAbout
limitquerynoHow many to return, 1 to 200
cursorquerynoThe next_cursor from the previous page

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Offer"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

GET /offers/{id}

Get an offer

Scope: offers:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

Offer

GET /leads

List leads from offers

Scope: offers:read.

ParameterInRequiredAbout
limitquerynoHow many to return, 1 to 200
cursorquerynoThe next_cursor from the previous page
offer_idquerynoAn id
statusquerynoOne of started, verified, signed, abandoned, discarded, converted_existing, awaiting_review, declined_by_business, review_expired
created_sincequeryno

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Lead"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

Clients

GET /clients

List clients

Newest first. Archived clients only with archived=true. Filter by a client field with field.<name>=<value> (values compare as text: true, 2, Single).

Scope: clients:read.

ParameterInRequiredAbout
limitquerynoHow many to return, 1 to 200
cursorquerynoThe next_cursor from the previous page
searchquerynostring
external_idquerynostring
emailquerynostring
archivedquerynoOne of true, false
has_open_proposalquerynoOne of true, false
updated_sincequeryno

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Client"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

POST /clients

Add a client

Checked like an import row: display_name, and an email or external_id. One email can belong to several clients (a person and their business, say), so an email already in use still makes a new client; email_shared_with lists the others.

Scope: clients:write.

ParameterInRequiredAbout
Idempotency-KeyheaderyesAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "external_id": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ]
    },
    "display_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "first_name": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ]
    },
    "email": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 254
        },
        {
          "type": "null"
        }
      ]
    },
    "phone": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 60
        },
        {
          "type": "null"
        }
      ]
    },
    "type": {
      "description": "individual (the default) or business: an entity, whose display_name is the business's name and whose contact signs for it",
      "type": "string",
      "enum": [
        "individual",
        "business"
      ]
    },
    "contact_name": {
      "description": "A business's contact person, in full. Business clients only",
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ]
    },
    "contact_title": {
      "description": "The contact's title (Managing Member), prefilled when they sign. Business clients only",
      "anyOf": [
        {
          "type": "string",
          "maxLength": 80
        },
        {
          "type": "null"
        }
      ]
    },
    "representative": {
      "description": "Someone else signs for this individual client (power of attorney, guardian, executor, or personal representative): name, email, optional phone, and capacity. Everything is sent to them and nothing to the client. null removes it. Refused on a business",
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "minLength": 1,
              "maxLength": 120
            },
            "email": {
              "type": "string"
            },
            "phone": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 40
                },
                {
                  "type": "null"
                }
              ]
            },
            "capacity": {
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            }
          },
          "required": [
            "name",
            "email",
            "capacity"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "prior_price_cents": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "fields": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": [
          "string",
          "number",
          "boolean",
          "null"
        ]
      }
    }
  },
  "additionalProperties": false
}

Answer 201

CreatedClient

GET /clients/{id}

Get a client

Scope: clients:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

Client

PATCH /clients/{id}

Change a client

Only what you send changes; null clears a value. Fields not sent keep their values, and hidden fields are never touched.

Scope: clients:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "external_id": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200
        },
        {
          "type": "null"
        }
      ]
    },
    "display_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "first_name": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ]
    },
    "email": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 254
        },
        {
          "type": "null"
        }
      ]
    },
    "phone": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 60
        },
        {
          "type": "null"
        }
      ]
    },
    "type": {
      "description": "individual (the default) or business: an entity, whose display_name is the business's name and whose contact signs for it",
      "type": "string",
      "enum": [
        "individual",
        "business"
      ]
    },
    "contact_name": {
      "description": "A business's contact person, in full. Business clients only",
      "anyOf": [
        {
          "type": "string",
          "maxLength": 120
        },
        {
          "type": "null"
        }
      ]
    },
    "contact_title": {
      "description": "The contact's title (Managing Member), prefilled when they sign. Business clients only",
      "anyOf": [
        {
          "type": "string",
          "maxLength": 80
        },
        {
          "type": "null"
        }
      ]
    },
    "representative": {
      "description": "Someone else signs for this individual client (power of attorney, guardian, executor, or personal representative): name, email, optional phone, and capacity. Everything is sent to them and nothing to the client. null removes it. Refused on a business",
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "minLength": 1,
              "maxLength": 120
            },
            "email": {
              "type": "string"
            },
            "phone": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 40
                },
                {
                  "type": "null"
                }
              ]
            },
            "capacity": {
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            }
          },
          "required": [
            "name",
            "email",
            "capacity"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "prior_price_cents": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "fields": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": [
          "string",
          "number",
          "boolean",
          "null"
        ]
      }
    }
  },
  "additionalProperties": false
}

Answer 200

Client

POST /clients/{id}/signing

Set who must sign a client's proposals

The default for new proposals when the client has signers besides themselves (Multiple signers): all of them, or any one. 403 without Multiple signers on the plan.

Scope: clients:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "rule": {
      "type": "string",
      "enum": [
        "all",
        "any"
      ]
    }
  },
  "required": [
    "rule"
  ],
  "additionalProperties": false
}

Answer 200

Client

POST /clients/{id}/archive

Archive a client

Archived clients leave lists, campaigns, and pickers; their history stays.

Scope: clients:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

Client

POST /clients/{id}/restore

Restore an archived client

Scope: clients:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

Client

GET /clients/{id}/people

List a client's people

People copied on the client's new proposals: they get a view-only link and the signed copy, and can never choose or sign.

Scope: clients:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/ClientPerson"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

POST /clients/{id}/people

Copy someone on a client's proposals

client_asked must be true: the client asked you to share their proposals with this person, and it's recorded with the API key and the time. The client's own email is refused. role signer needs Multiple signers on the plan (400 validation otherwise).

Scope: clients:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheaderyesAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 120
    },
    "email": {
      "type": "string",
      "maxLength": 254
    },
    "phone": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 40
        },
        {
          "type": "null"
        }
      ]
    },
    "relationship": {
      "type": "string",
      "enum": [
        "spouse",
        "family",
        "assistant",
        "business_partner",
        "other"
      ]
    },
    "title": {
      "description": "Their title at the business (Member, Partner); used only on a business client",
      "anyOf": [
        {
          "type": "string",
          "maxLength": 80
        },
        {
          "type": "null"
        }
      ]
    },
    "role": {
      "description": "copied (the default), or signer where the business has Multiple signers",
      "type": "string",
      "enum": [
        "copied",
        "signer"
      ]
    },
    "client_asked": {
      "description": "The client asked you to share their proposal with this person; required to add someone or change their email",
      "type": "boolean"
    }
  },
  "required": [
    "name",
    "email",
    "relationship"
  ],
  "additionalProperties": false
}

Answer 201

ClientPerson

PATCH /clients/{id}/people/{personId}

Change one of a client's people

Only what you send changes. A new email needs client_asked: true again. Proposals already sent keep who they were sent to.

Scope: clients:write.

ParameterInRequiredAbout
idpathyesAn id
personIdpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 120
    },
    "email": {
      "type": "string",
      "maxLength": 254
    },
    "phone": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 40
        },
        {
          "type": "null"
        }
      ]
    },
    "relationship": {
      "type": "string",
      "enum": [
        "spouse",
        "family",
        "assistant",
        "business_partner",
        "other"
      ]
    },
    "title": {
      "description": "Their title at the business (Member, Partner); used only on a business client",
      "anyOf": [
        {
          "type": "string",
          "maxLength": 80
        },
        {
          "type": "null"
        }
      ]
    },
    "role": {
      "description": "copied (the default), or signer where the business has Multiple signers",
      "type": "string",
      "enum": [
        "copied",
        "signer"
      ]
    },
    "client_asked": {
      "description": "The client asked you to share their proposal with this person; required to add someone or change their email",
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

Answer 200

ClientPerson

DELETE /clients/{id}/people/{personId}

Stop copying someone on a client's proposals

Proposals already sent keep who they were sent to.

Scope: clients:write.

ParameterInRequiredAbout
idpathyesAn id
personIdpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "deleted": {
      "type": "boolean",
      "const": true
    }
  },
  "required": [
    "id",
    "deleted"
  ],
  "additionalProperties": false
}

POST /clients/batch

Import clients as JSON rows

{ rows: [ { external_id, display_name, email, first_name, phone, prior_price, client_type, business_name, contact_name, contact_title, <field>: value } ] }, 1 to 5,000 rows. prior_price is in major units (350.00), like a CSV. client_type is Individual or Business; a row with a business_name is a business named for it, and its display_name is the contact when contact_name is empty. A column a row leaves out keeps the client's value. A column no client field takes is 422 unknown_columns.

Scope: clients:write.

ParameterInRequiredAbout
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{}

Answer 200

ImportSummary

POST /clients/import

Import clients from a CSV file

text/csv (text/plain and application/octet-stream are read as CSV too), or multipart form data with a file field. The same columns as POST /clients/batch, business columns included. 1 to 5,000 data rows: 413 too_many_rows past that. A column no client field takes is 422 unknown_columns.

Scope: clients:write.

ParameterInRequiredAbout
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

text/csv: A CSV with a header row

multipart/form-data: A CSV with a header row

Answer 200

ImportSummary

Catalog

GET /catalog

List catalog items

Active items unless status says otherwise. Prices are minor units; unit_cents is null for no price yet.

Scope: catalog:read.

ParameterInRequiredAbout
limitquerynoHow many to return, 1 to 200
cursorquerynoThe next_cursor from the previous page
statusquerynoOne of active, archived, all

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/CatalogItem"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

POST /catalog

Add a catalog item

A single item has min_qty and max_qty 1; a counted one (per location, per return) sets a range and a unit_label. A rate billed as used sets billed_as_used and a unit_label (per form): it has no quantity and is never in a total. A unit_cents other than null needs the catalog:prices scope. Changing the catalog never changes proposals already made.

Scope: catalog:write.

ParameterInRequiredAbout
Idempotency-KeyheaderyesAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 120
    },
    "category": {
      "default": "",
      "type": "string",
      "maxLength": 60
    },
    "description": {
      "default": "",
      "type": "string",
      "maxLength": 500
    },
    "includes": {
      "default": [],
      "maxItems": 20,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 200
      }
    },
    "unit_label": {
      "default": "",
      "type": "string",
      "maxLength": 40
    },
    "unit_plural": {
      "default": "",
      "type": "string",
      "maxLength": 40
    },
    "unit_cents": {
      "default": null,
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "billing": {
      "default": "one_time",
      "type": "string",
      "enum": [
        "one_time",
        "yearly",
        "semiannual",
        "quarterly",
        "monthly",
        "weekly"
      ]
    },
    "min_qty": {
      "default": 1,
      "type": "integer",
      "minimum": 0,
      "maximum": 999
    },
    "max_qty": {
      "default": 1,
      "type": "integer",
      "minimum": 1,
      "maximum": 999
    },
    "billed_as_used": {
      "default": false,
      "type": "boolean"
    }
  },
  "required": [
    "name"
  ],
  "additionalProperties": false
}

Answer 201

CatalogItem

GET /catalog/{id}

Get a catalog item

Scope: catalog:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

CatalogItem

PATCH /catalog/{id}

Change a catalog item

Only what you send changes. An archived item must be restored first. Changing unit_cents needs the catalog:prices scope; a price change is logged with the old and new price, and live offers price from the catalog, so they use the new price at once.

Scope: catalog:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 120
    },
    "category": {
      "type": "string",
      "maxLength": 60
    },
    "description": {
      "type": "string",
      "maxLength": 500
    },
    "includes": {
      "maxItems": 20,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 200
      }
    },
    "unit_label": {
      "type": "string",
      "maxLength": 40
    },
    "unit_plural": {
      "type": "string",
      "maxLength": 40
    },
    "unit_cents": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 100000000
        },
        {
          "type": "null"
        }
      ]
    },
    "billing": {
      "type": "string",
      "enum": [
        "one_time",
        "yearly",
        "semiannual",
        "quarterly",
        "monthly",
        "weekly"
      ]
    },
    "min_qty": {
      "type": "integer",
      "minimum": 0,
      "maximum": 999
    },
    "max_qty": {
      "type": "integer",
      "minimum": 1,
      "maximum": 999
    },
    "billed_as_used": {
      "type": "boolean"
    }
  },
  "additionalProperties": false
}

Answer 200

CatalogItem

POST /catalog/{id}/archive

Archive a catalog item

It leaves pickers; proposals and presets that hold it keep their copy.

Scope: catalog:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

CatalogItem

POST /catalog/{id}/restore

Restore a catalog item

Scope: catalog:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

CatalogItem

Proposals

GET /proposals

List proposals

Newest first. Without status, everything that went out (no drafts); status=draft lists drafts made in the builder or the API. since is kept as another name for updated_since.

Scope: proposals:read.

ParameterInRequiredAbout
limitquerynoHow many to return, 1 to 200
cursorquerynoThe next_cursor from the previous page
statusquerynoOne of draft, sent, viewed, signed, declined, expired, revoked, superseded
handoffquerynoOne of pending, confirmed, failed
client_idquerynoAn id
campaign_idquerynoAn id
offer_idquerynoAn id
template_idquerynoAn id
created_sincequeryno
updated_sincequeryno
signed_sincequeryno
sincequeryno

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Proposal"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

POST /proposals

Make a draft proposal

For one client, from a preset (preset_id), from a build in the short form (build), or empty. template_id defaults to the business's default template. It starts with the client's copied people; copied_people replaces them for this proposal only. Nothing is sent: preview it, then send it.

Scope: proposals:write.

ParameterInRequiredAbout
Idempotency-KeyheaderyesAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "client_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "preset_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "template_id": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    },
    "note": {
      "type": "string",
      "maxLength": 2000
    },
    "period": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string",
          "minLength": 1,
          "maxLength": 40
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 80
        }
      },
      "required": [
        "key",
        "label"
      ],
      "additionalProperties": false
    },
    "expiry_days": {
      "type": "integer",
      "minimum": 1,
      "maximum": 365
    },
    "build": {
      "type": "object",
      "properties": {
        "mode": {
          "type": "string",
          "enum": [
            "fixed",
            "choose"
          ]
        },
        "packages": {
          "minItems": 1,
          "maxItems": 8,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "badge": {
                "default": null,
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 40
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "description": {
                "default": "",
                "type": "string",
                "maxLength": 500
              },
              "items": {
                "default": [],
                "maxItems": 60,
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "catalog_item_id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "qty": {
                          "default": 1,
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 999
                        },
                        "unit_cents": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 100000000
                        },
                        "unit_label": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "unit_plural": {
                          "type": "string",
                          "maxLength": 40
                        }
                      },
                      "required": [
                        "catalog_item_id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 120
                        },
                        "description": {
                          "default": "",
                          "type": "string",
                          "maxLength": 500
                        },
                        "includes": {
                          "default": [],
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 200
                          }
                        },
                        "unit_label": {
                          "default": "",
                          "type": "string",
                          "maxLength": 40
                        },
                        "unit_plural": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "unit_cents": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 100000000
                        },
                        "qty": {
                          "default": 1,
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 999
                        },
                        "billing": {
                          "default": "one_time",
                          "type": "string",
                          "enum": [
                            "one_time",
                            "yearly",
                            "semiannual",
                            "quarterly",
                            "monthly",
                            "weekly"
                          ]
                        },
                        "billed_as_used": {
                          "default": false,
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "name",
                        "unit_cents"
                      ],
                      "additionalProperties": false
                    }
                  ]
                }
              }
            },
            "required": [
              "name"
            ],
            "additionalProperties": false
          }
        },
        "addons": {
          "default": [],
          "maxItems": 30,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "catalog_item_id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "description": {
                "type": "string",
                "maxLength": 500
              },
              "unit_label": {
                "type": "string",
                "maxLength": 40
              },
              "unit_plural": {
                "type": "string",
                "maxLength": 40
              },
              "unit_cents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100000000
              },
              "billing": {
                "type": "string",
                "enum": [
                  "one_time",
                  "yearly",
                  "semiannual",
                  "quarterly",
                  "monthly",
                  "weekly"
                ]
              },
              "billed_as_used": {
                "type": "boolean"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "toggle",
                  "quantity"
                ]
              },
              "min_qty": {
                "default": 0,
                "type": "integer",
                "minimum": 0,
                "maximum": 999
              },
              "max_qty": {
                "type": "integer",
                "minimum": 1,
                "maximum": 999
              },
              "only_with": {
                "default": null,
                "anyOf": [
                  {
                    "maxItems": 8,
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 7
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "kind"
            ],
            "additionalProperties": false
          }
        },
        "discounts": {}
      },
      "required": [
        "mode",
        "packages"
      ],
      "additionalProperties": false
    },
    "copied_people": {
      "maxItems": 10,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "maxLength": 254
          },
          "phone": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 40
              },
              {
                "type": "null"
              }
            ]
          },
          "relationship": {
            "type": "string",
            "enum": [
              "spouse",
              "family",
              "assistant",
              "business_partner",
              "other"
            ]
          },
          "title": {
            "description": "Their title at the business (Member, Partner); used only on a business client",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80
              },
              {
                "type": "null"
              }
            ]
          },
          "role": {
            "description": "copied (the default), or signer where the business has Multiple signers",
            "type": "string",
            "enum": [
              "copied",
              "signer"
            ]
          },
          "client_asked": {
            "description": "The client asked you to share their proposal with this person; required to add someone or change their email",
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "email",
          "relationship"
        ],
        "additionalProperties": false
      }
    },
    "copied_signed_copy": {
      "type": "boolean"
    },
    "signing": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "rule": {
              "type": "string",
              "enum": [
                "all",
                "any"
              ]
            },
            "order": {
              "default": "any",
              "type": "string",
              "enum": [
                "any",
                "in_order"
              ]
            }
          },
          "required": [
            "rule"
          ]
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "client_id"
  ],
  "additionalProperties": false
}

Answer 201

ProposalDetail

GET /proposals/{id}

Get a proposal

With copied_people: everyone copied on it, whether their view-only link was emailed, and when they last looked.

Scope: proposals:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

ProposalDetail

PATCH /proposals/{id}

Change a draft

Any change to the document throws away the preview; changing only copied_people or copied_signed_copy keeps it. A build sent here replaces the draft's packages and add-ons. 409 invalid_state once it's sent.

Scope: proposals:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "template_id": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    },
    "note": {
      "type": "string",
      "maxLength": 2000
    },
    "period": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string",
          "minLength": 1,
          "maxLength": 40
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 80
        }
      },
      "required": [
        "key",
        "label"
      ],
      "additionalProperties": false
    },
    "expiry_days": {
      "type": "integer",
      "minimum": 1,
      "maximum": 365
    },
    "build": {
      "type": "object",
      "properties": {
        "mode": {
          "type": "string",
          "enum": [
            "fixed",
            "choose"
          ]
        },
        "packages": {
          "minItems": 1,
          "maxItems": 8,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "badge": {
                "default": null,
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 40
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "description": {
                "default": "",
                "type": "string",
                "maxLength": 500
              },
              "items": {
                "default": [],
                "maxItems": 60,
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "catalog_item_id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "qty": {
                          "default": 1,
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 999
                        },
                        "unit_cents": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 100000000
                        },
                        "unit_label": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "unit_plural": {
                          "type": "string",
                          "maxLength": 40
                        }
                      },
                      "required": [
                        "catalog_item_id"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 120
                        },
                        "description": {
                          "default": "",
                          "type": "string",
                          "maxLength": 500
                        },
                        "includes": {
                          "default": [],
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 200
                          }
                        },
                        "unit_label": {
                          "default": "",
                          "type": "string",
                          "maxLength": 40
                        },
                        "unit_plural": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "unit_cents": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 100000000
                        },
                        "qty": {
                          "default": 1,
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 999
                        },
                        "billing": {
                          "default": "one_time",
                          "type": "string",
                          "enum": [
                            "one_time",
                            "yearly",
                            "semiannual",
                            "quarterly",
                            "monthly",
                            "weekly"
                          ]
                        },
                        "billed_as_used": {
                          "default": false,
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "name",
                        "unit_cents"
                      ],
                      "additionalProperties": false
                    }
                  ]
                }
              }
            },
            "required": [
              "name"
            ],
            "additionalProperties": false
          }
        },
        "addons": {
          "default": [],
          "maxItems": 30,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "catalog_item_id": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "description": {
                "type": "string",
                "maxLength": 500
              },
              "unit_label": {
                "type": "string",
                "maxLength": 40
              },
              "unit_plural": {
                "type": "string",
                "maxLength": 40
              },
              "unit_cents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100000000
              },
              "billing": {
                "type": "string",
                "enum": [
                  "one_time",
                  "yearly",
                  "semiannual",
                  "quarterly",
                  "monthly",
                  "weekly"
                ]
              },
              "billed_as_used": {
                "type": "boolean"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "toggle",
                  "quantity"
                ]
              },
              "min_qty": {
                "default": 0,
                "type": "integer",
                "minimum": 0,
                "maximum": 999
              },
              "max_qty": {
                "type": "integer",
                "minimum": 1,
                "maximum": 999
              },
              "only_with": {
                "default": null,
                "anyOf": [
                  {
                    "maxItems": 8,
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 7
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "kind"
            ],
            "additionalProperties": false
          }
        },
        "discounts": {}
      },
      "required": [
        "mode",
        "packages"
      ],
      "additionalProperties": false
    },
    "copied_people": {
      "maxItems": 10,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "maxLength": 254
          },
          "phone": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 40
              },
              {
                "type": "null"
              }
            ]
          },
          "relationship": {
            "type": "string",
            "enum": [
              "spouse",
              "family",
              "assistant",
              "business_partner",
              "other"
            ]
          },
          "title": {
            "description": "Their title at the business (Member, Partner); used only on a business client",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80
              },
              {
                "type": "null"
              }
            ]
          },
          "role": {
            "description": "copied (the default), or signer where the business has Multiple signers",
            "type": "string",
            "enum": [
              "copied",
              "signer"
            ]
          },
          "client_asked": {
            "description": "The client asked you to share their proposal with this person; required to add someone or change their email",
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "email",
          "relationship"
        ],
        "additionalProperties": false
      }
    },
    "copied_signed_copy": {
      "type": "boolean"
    },
    "signing": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "rule": {
              "type": "string",
              "enum": [
                "all",
                "any"
              ]
            },
            "order": {
              "default": "any",
              "type": "string",
              "enum": [
                "any",
                "in_order"
              ]
            }
          },
          "required": [
            "rule"
          ]
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "additionalProperties": false
}

Answer 200

ProposalDetail

POST /proposals/{id}/copied/{personId}/resend

Send a copied person their copy again

Emails them their view-only link again: the same link while the proposal is open, otherwise a new one (their earlier link stops). After Remove access it gives them a new link. Needs an email sender; refused while email is paused, as other sends are.

Scope: proposals:send.

ParameterInRequiredAbout
idpathyesAn id
personIdpathyesAn id
Idempotency-KeyheaderyesAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

CopyResent

POST /proposals/{id}/copied/{personId}/remove-access

Remove a copied person's access

Their link says it's no longer active, for good, and they get no signed copy or withdrawn notice. Send their copy again to give them a new link.

Scope: proposals:write.

ParameterInRequiredAbout
idpathyesAn id
personIdpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

CopiedPerson

POST /proposals/{id}/preview

Preview a draft

Freezes exactly what the client would get and fixes its respond-by date. Send needs this preview_sha256. A preview goes stale at the end of the business's day or after 24 hours.

Scope: proposals:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

Preview

GET /proposals/{id}/preview/document

The previewed document

The rendered HTML of the stored preview, the same as the client will see.

Scope: proposals:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

text/html

POST /proposals/{id}/send

Send a previewed draft

Needs the preview_sha256 from the preview: 409 not_previewed, preview_changed, or preview_stale otherwise. email: true emails the link (409 send_blocked while email is paused, as in the admin); false makes the link without emailing it. Uses a credit (402 out_of_credits when there's none); a revision is free, unless the version it replaces was withdrawn before the client opened it, which gave its credit back. The link is never in this answer: read it with GET /proposals/{id}/link.

Scope: proposals:send.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheaderyesAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "preview_sha256": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$"
    },
    "email": {
      "type": "boolean"
    },
    "email_copied": {
      "type": "boolean"
    }
  },
  "required": [
    "preview_sha256",
    "email"
  ],
  "additionalProperties": false
}

Answer 200

Sent

POST /proposals/{id}/withdraw

Withdraw a sent proposal

Its link then says it was withdrawn. email_client emails the client the withdrawn notice when the business has a sender. Withdrawn before it was opened, its credit comes back.

Scope: proposals:send.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "email_client": {
      "type": "boolean"
    },
    "note": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 1000
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "email_client"
  ],
  "additionalProperties": false
}

Answer 200

Withdrawn

POST /proposals/{id}/resend

Resend a sent proposal's link to the client

The admin's Resend: the client gets a new link and their earlier links stop working. An expired proposal reopens only within 30 days of its deadline: it's extended first (proposal.deadline_extended, with the reason "Sent a new link") to expiry_days from today, and the date the document printed doesn't change. After 30 days, or for a withdrawn one, it's refused (409 invalid_state); revise it to send it again. emailed is false when the business has no email sender (proposal.sent tells your automation). The link is never in this answer.

Scope: proposals:send.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheaderyesAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

Resent

POST /proposals/{id}/extend

Extend a sent proposal's deadline

More time on the same proposal: the link the client has keeps working, and the document keeps the respond-by date it printed. Open proposals any time before the deadline; an expired one within 30 days of its deadline, which reopens it. notify_client (default true) emails a second link with the new date. Its expires_at is then the new deadline, with original_expires_at the printed date. 409 invalid_state for a draft, a closed proposal, one that ended more than 30 days ago, or one in a walkthrough (extend the walkthrough in EngageCycle); 422 validation for the date. Writes proposal.deadline_extended.

Scope: proposals:send.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheaderyesAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "expires_on": {
      "type": "string",
      "maxLength": 40,
      "description": "The new deadline, a date in the business's time zone (YYYY-MM-DD). It ends at the end of that day. Later than the current deadline, not in the past, and at most 180 days from today."
    },
    "reason": {
      "description": "Why, for the business's own team: in the activity and the event, never shown to the client",
      "anyOf": [
        {
          "type": "string",
          "maxLength": 500
        },
        {
          "type": "null"
        }
      ]
    },
    "notify_client": {
      "description": "Email the client (and each signer whose turn it is) a second link with the new date; the link they have keeps working. Default true.",
      "type": "boolean"
    }
  },
  "required": [
    "expires_on"
  ],
  "additionalProperties": false
}

Answer 200

Extended

POST /proposals/{id}/revise

Start a revision

A draft copied from what was sent (or the revision already started). Sending it replaces the old version, and the old link leads to it.

Scope: proposals:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheaderyesAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 201

Revision

GET /proposals/{id}/pdf

The signed PDF

With the certificate page. X-EngageCycle-Sha256 is the file's hash. 409 not_signed before it's signed, and pdf_not_ready while it's being made.

Scope: proposals:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

application/pdf

Automation

POST /proposals/{id}/handoff

Record the handoff of a signed proposal

Your automation says it filed the signed proposal (confirmed) or couldn't (failed).

Scope: proposals:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "confirmed",
        "failed"
      ]
    },
    "detail": {
      "type": "string",
      "maxLength": 2000
    }
  },
  "required": [
    "status"
  ],
  "additionalProperties": false
}

Answer 200

{
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean",
      "const": true
    },
    "handoff": {
      "type": "object",
      "properties": {
        "status": {
          "type": "string"
        },
        "at": {
          "anyOf": [
            {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            {
              "type": "null"
            }
          ]
        },
        "detail": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "status",
        "at",
        "detail"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "ok",
    "handoff"
  ],
  "additionalProperties": false
}

POST /proposals/{id}/booked

Record a booked call

Scope: proposals:write.

ParameterInRequiredAbout
idpathyesAn id
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "provider": {
      "type": "string",
      "minLength": 1,
      "maxLength": 40
    },
    "external_id": {
      "type": "string",
      "maxLength": 200
    },
    "starts_at": {},
    "source": {
      "default": "api",
      "type": "string",
      "maxLength": 40
    }
  },
  "required": [
    "provider"
  ]
}

Answer 200

{
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean",
      "const": true
    },
    "proposal_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "booked": {
      "type": "boolean",
      "const": true
    }
  },
  "required": [
    "ok",
    "proposal_id",
    "booked"
  ],
  "additionalProperties": false
}

POST /bookings/match

Match a booking to an open proposal by email

404 no_open_proposal when the email has none, so bookings that aren't about a proposal can be ignored. When several clients use the email (a person and their business, say), each one's open proposal is booked.

Scope: proposals:write.

ParameterInRequiredAbout
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Body

{
  "type": "object",
  "properties": {
    "provider": {
      "type": "string",
      "minLength": 1,
      "maxLength": 40
    },
    "external_id": {
      "type": "string",
      "maxLength": 200
    },
    "starts_at": {},
    "source": {
      "default": "api",
      "type": "string",
      "maxLength": 40
    },
    "email": {
      "type": "string",
      "format": "email",
      "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
    }
  },
  "required": [
    "provider",
    "email"
  ]
}

Answer 200

{
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean",
      "const": true
    },
    "proposal_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "description": "The newest open proposal booked"
    },
    "booked": {
      "type": "boolean",
      "const": true
    },
    "proposal_ids": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
      },
      "description": "Every open proposal booked, newest first. One email can belong to several clients (a person and their business, say), and each one's open proposal is marked."
    }
  },
  "required": [
    "ok",
    "proposal_id",
    "booked",
    "proposal_ids"
  ],
  "additionalProperties": false
}

Documents

GET /documents

List documents

Agreements and consents sent on their own, newest first (never a draft, never a proposal). 403 forbidden when Agreement and Consent aren't on the plan.

Scope: documents:read.

ParameterInRequiredAbout
limitquerynoHow many to return, 1 to 200
cursorquerynoThe next_cursor from the previous page
kindquerynoOne of agreement, consent
statusquerynoOne of sent, viewed, signed, declined, expired, revoked, superseded
client_idquerynoAn id
sincequerynoChanged since this time

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Document"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

GET /documents/{id}

Get a document

Its kind, template, status, client, signers (position and answer), and the signature once signed. A proposal's id is not found here.

Scope: documents:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

Document

GET /documents/{id}/pdf

The signed PDF

With the certificate page. X-EngageCycle-Sha256 is the file's hash. 409 not_signed or pdf_not_ready while there isn't one.

Scope: documents:read.

ParameterInRequiredAbout
idpathyesAn id

Answer 200

application/pdf

Events

GET /events

List events

The same envelope as the webhook, oldest first, every event recorded (also those recorded while the webhook was off). Pass the last next_cursor as since to get only what's new; an event never appears before one that was written earlier and is still being committed, so polling misses nothing. type can repeat. Documents' events (document.*) come back only when named in type, with the documents:read scope. Links in payloads come back only with the proposals:links scope.

Scope: events:read.

ParameterInRequiredAbout
typequerynoText, or repeat it for several
proposal_idquerynoAn id
sincequerynostring
limitquerynointeger

Answer 200

{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Event"
      }
    },
    "next_cursor": {
      "description": "Pass as cursor (or since, for events) to get the next page; null at the end",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ],
  "additionalProperties": false
}

POST /events/{id}/redeliver

Send an event to your webhook again

Marks a delivered or failed event to be delivered again, with the same event id and a new signature. 409 webhook_off when the webhook isn't on.

Scope: events:write.

ParameterInRequiredAbout
idpathyesstring
Idempotency-KeyheadernoAny unique string, up to 200 characters. Repeating the request with the same key within 24 hours returns the first answer instead of doing it again.

Answer 200

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "type": {
      "type": "string"
    },
    "delivery": {
      "type": "string",
      "const": "due"
    }
  },
  "required": [
    "id",
    "type",
    "delivery"
  ],
  "additionalProperties": false
}

Shapes

Error

{
  "type": "object",
  "properties": {
    "error": {
      "type": "object",
      "properties": {
        "code": {
          "type": "string",
          "description": "Stable code to branch on"
        },
        "message": {
          "type": "string",
          "description": "Words for a person"
        },
        "field": {
          "description": "The input at fault, as a dotted path",
          "type": "string"
        },
        "details": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "scope": {
          "description": "missing_scope: the scope the key needs",
          "type": "string"
        },
        "columns": {
          "description": "unknown_columns: the columns",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "request_id": {
          "description": "internal_error: quote it to support",
          "type": "string"
        }
      },
      "required": [
        "code",
        "message"
      ],
      "additionalProperties": {}
    }
  },
  "required": [
    "error"
  ],
  "additionalProperties": false
}

Me

{
  "type": "object",
  "properties": {
    "tenant": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "slug": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "currency": {
          "type": "string"
        },
        "timezone": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "slug",
        "name",
        "currency",
        "timezone"
      ],
      "additionalProperties": false
    },
    "key": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "prefix": {
          "type": "string"
        },
        "scopes": {
          "anyOf": [
            {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            {
              "type": "null"
            }
          ],
          "description": "null: full access (a legacy key)"
        }
      },
      "required": [
        "name",
        "prefix",
        "scopes"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "tenant",
    "key"
  ],
  "additionalProperties": false
}

Credits

{
  "type": "object",
  "properties": {
    "tracked": {
      "type": "boolean",
      "description": "false before credits start for the business"
    },
    "plan": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "name": {
              "type": "string"
            },
            "included_credits": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "year_start": {
              "type": [
                "string",
                "null"
              ]
            },
            "year_end": {
              "type": [
                "string",
                "null"
              ]
            },
            "overage_rule": {
              "type": "string"
            },
            "overage_cap": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                {
                  "type": "null"
                }
              ]
            }
          },
          "required": [
            "name",
            "included_credits",
            "year_start",
            "year_end",
            "overage_rule",
            "overage_cap"
          ],
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ]
    },
    "total": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "used": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "left": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "overage_used": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "overage_room": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "can_send": {
      "type": "boolean"
    }
  },
  "required": [
    "tracked",
    "plan",
    "can_send"
  ],
  "additionalProperties": false
}

Template

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "slug": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "kind": {
      "type": "string"
    },
    "version": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "default": {
      "type": "boolean"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "slug",
    "name",
    "title",
    "kind",
    "version",
    "default",
    "created_at"
  ],
  "additionalProperties": false
}

Preset

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": "string"
    },
    "mode": {
      "type": "string",
      "enum": [
        "fixed",
        "choose"
      ]
    },
    "currency": {
      "type": "string"
    },
    "packages": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "total_cents": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Kept for compatibility: one-time plus yearly. Use totals, which also carries amounts billed every six months, quarterly, or weekly."
          },
          "monthly_cents": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Kept for compatibility: the monthly amount. Use totals."
          },
          "totals": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BillingTotals"
              },
              {
                "type": "null"
              }
            ],
            "description": "null while an item has no price"
          }
        },
        "required": [
          "id",
          "name",
          "total_cents",
          "monthly_cents",
          "totals"
        ],
        "additionalProperties": false
      }
    },
    "addons": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "unit_cents": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "name",
          "unit_cents"
        ],
        "additionalProperties": false
      }
    },
    "unpriced": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "archived": {
      "type": "boolean"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "description",
    "mode",
    "currency",
    "packages",
    "addons",
    "unpriced",
    "archived",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

BillingTotals

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "billing": {
        "type": "string",
        "enum": [
          "one_time",
          "yearly",
          "semiannual",
          "quarterly",
          "monthly",
          "weekly"
        ]
      },
      "cents": {
        "type": "integer",
        "minimum": -9007199254740991,
        "maximum": 9007199254740991
      }
    },
    "required": [
      "billing",
      "cents"
    ],
    "additionalProperties": false
  },
  "description": "Each billing frequency's own total, in order: one_time, yearly, semiannual, quarterly, monthly, weekly. Only frequencies with an amount are listed; with none, a single one_time total of 0."
}

Campaign

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "name": {
      "type": "string"
    },
    "kind": {
      "type": "string"
    },
    "status": {
      "type": "string"
    },
    "template_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "batch_size": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "batch_every_minutes": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "next_batch_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "held": {
      "type": "boolean",
      "description": "Paused by EngageCycle support"
    },
    "counts": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": "integer",
        "minimum": -9007199254740991,
        "maximum": 9007199254740991
      },
      "description": "Proposals by status"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "kind",
    "status",
    "template_id",
    "batch_size",
    "batch_every_minutes",
    "next_batch_at",
    "held",
    "counts",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

Offer

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "name": {
      "type": "string"
    },
    "slug": {
      "type": "string"
    },
    "status": {
      "type": "string"
    },
    "availability": {
      "type": "string"
    },
    "url": {
      "type": "string"
    },
    "opens_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "closes_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "template_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "funnel": {
      "type": "object",
      "properties": {
        "visits": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "started": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "verified": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "signed": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "abandoned": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "visits",
        "started",
        "verified",
        "signed",
        "abandoned"
      ],
      "additionalProperties": false
    },
    "archived": {
      "type": "boolean"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "slug",
    "status",
    "availability",
    "url",
    "opens_at",
    "closes_at",
    "template_id",
    "funnel",
    "archived",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

Lead

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "offer_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "status": {
      "type": "string",
      "description": "started, verified, signed, abandoned, discarded, converted_existing, or, on an offer that holds requests for review, awaiting_review, declined_by_business, or review_expired"
    },
    "outcome": {
      "type": [
        "string",
        "null"
      ]
    },
    "email": {
      "type": "string"
    },
    "name": {
      "type": [
        "string",
        "null"
      ]
    },
    "phone": {
      "type": [
        "string",
        "null"
      ]
    },
    "answers": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {},
      "description": "Keyed by question id"
    },
    "utm": {
      "anyOf": [
        {
          "type": "object",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {
            "type": "string"
          }
        },
        {
          "type": "null"
        }
      ]
    },
    "marketing_consent": {
      "type": "boolean"
    },
    "client_id": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    },
    "proposal_id": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    },
    "verified_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "contacted_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "last_activity_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "offer_id",
    "status",
    "outcome",
    "email",
    "name",
    "phone",
    "answers",
    "utm",
    "marketing_consent",
    "client_id",
    "proposal_id",
    "verified_at",
    "contacted_at",
    "last_activity_at",
    "created_at"
  ],
  "additionalProperties": false
}

Client

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "external_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "display_name": {
      "type": "string"
    },
    "first_name": {
      "type": [
        "string",
        "null"
      ]
    },
    "email": {
      "type": [
        "string",
        "null"
      ]
    },
    "phone": {
      "type": [
        "string",
        "null"
      ]
    },
    "type": {
      "type": "string",
      "enum": [
        "individual",
        "business"
      ],
      "description": "individual (a person, and every client nobody marked) or business (an entity)"
    },
    "contact_name": {
      "description": "A business's contact person, in full; null for an individual",
      "type": [
        "string",
        "null"
      ]
    },
    "contact_title": {
      "description": "The contact's title (Managing Member), prefilled when they sign; business only",
      "type": [
        "string",
        "null"
      ]
    },
    "representative": {
      "description": "Someone else signs for this individual client: everything is sent to them, nothing to the client. Absent when the client signs",
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "phone": {
          "type": [
            "string",
            "null"
          ]
        },
        "capacity": {
          "type": "string",
          "enum": [
            "power_of_attorney",
            "guardian",
            "executor",
            "personal_representative"
          ]
        }
      },
      "required": [
        "name",
        "email",
        "phone",
        "capacity"
      ],
      "additionalProperties": false
    },
    "prior_price_cents": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        {
          "type": "null"
        }
      ]
    },
    "currency": {
      "type": "string"
    },
    "fields": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "is_new": {
      "type": "boolean"
    },
    "source": {
      "type": "string"
    },
    "archived": {
      "type": "boolean"
    },
    "archived_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "signing_rule": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "all",
            "any"
          ]
        },
        {
          "type": "null"
        }
      ],
      "description": "Who must sign this client's proposals by default (Multiple signers); null is all"
    },
    "has_open_proposal": {
      "type": "boolean"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "external_id",
    "display_name",
    "first_name",
    "email",
    "phone",
    "type",
    "contact_name",
    "contact_title",
    "prior_price_cents",
    "currency",
    "fields",
    "is_new",
    "source",
    "archived",
    "archived_at",
    "signing_rule",
    "has_open_proposal",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

CreatedClient

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "external_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "display_name": {
      "type": "string"
    },
    "first_name": {
      "type": [
        "string",
        "null"
      ]
    },
    "email": {
      "type": [
        "string",
        "null"
      ]
    },
    "phone": {
      "type": [
        "string",
        "null"
      ]
    },
    "type": {
      "type": "string",
      "enum": [
        "individual",
        "business"
      ],
      "description": "individual (a person, and every client nobody marked) or business (an entity)"
    },
    "contact_name": {
      "description": "A business's contact person, in full; null for an individual",
      "type": [
        "string",
        "null"
      ]
    },
    "contact_title": {
      "description": "The contact's title (Managing Member), prefilled when they sign; business only",
      "type": [
        "string",
        "null"
      ]
    },
    "representative": {
      "description": "Someone else signs for this individual client: everything is sent to them, nothing to the client. Absent when the client signs",
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "phone": {
          "type": [
            "string",
            "null"
          ]
        },
        "capacity": {
          "type": "string",
          "enum": [
            "power_of_attorney",
            "guardian",
            "executor",
            "personal_representative"
          ]
        }
      },
      "required": [
        "name",
        "email",
        "phone",
        "capacity"
      ],
      "additionalProperties": false
    },
    "prior_price_cents": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        {
          "type": "null"
        }
      ]
    },
    "currency": {
      "type": "string"
    },
    "fields": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "is_new": {
      "type": "boolean"
    },
    "source": {
      "type": "string"
    },
    "archived": {
      "type": "boolean"
    },
    "archived_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "signing_rule": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "all",
            "any"
          ]
        },
        {
          "type": "null"
        }
      ],
      "description": "Who must sign this client's proposals by default (Multiple signers); null is all"
    },
    "has_open_proposal": {
      "type": "boolean"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "email_shared_with": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
      },
      "description": "Other clients that already use this email, by id, oldest first; empty when none. One email can belong to several clients, such as a person and their business."
    }
  },
  "required": [
    "id",
    "external_id",
    "display_name",
    "first_name",
    "email",
    "phone",
    "type",
    "contact_name",
    "contact_title",
    "prior_price_cents",
    "currency",
    "fields",
    "is_new",
    "source",
    "archived",
    "archived_at",
    "signing_rule",
    "has_open_proposal",
    "created_at",
    "updated_at",
    "email_shared_with"
  ],
  "additionalProperties": false
}

ClientPerson

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "client_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "phone": {
      "type": [
        "string",
        "null"
      ]
    },
    "title": {
      "description": "Their title at the business (Member, Partner); used only on a business client",
      "type": [
        "string",
        "null"
      ]
    },
    "relationship": {
      "type": "string",
      "enum": [
        "spouse",
        "family",
        "assistant",
        "business_partner",
        "other"
      ]
    },
    "role": {
      "type": "string",
      "enum": [
        "copied",
        "signer"
      ]
    },
    "client_asked_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
      "description": "When someone confirmed the client asked to share with them"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "client_id",
    "name",
    "email",
    "phone",
    "title",
    "relationship",
    "role",
    "client_asked_at",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

ImportSummary

{
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean"
    },
    "summary": {
      "type": "object",
      "properties": {
        "received": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "imported": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "created": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "updated": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "rejected": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "received",
        "imported",
        "created",
        "updated",
        "rejected"
      ],
      "additionalProperties": false
    },
    "errors": {
      "type": "array",
      "items": {}
    }
  },
  "required": [
    "ok",
    "summary",
    "errors"
  ],
  "additionalProperties": {}
}

CatalogItem

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "name": {
      "type": "string"
    },
    "category": {
      "description": "null: no category",
      "type": [
        "string",
        "null"
      ]
    },
    "description": {
      "type": "string"
    },
    "includes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "unit_label": {
      "description": "null: no unit",
      "type": [
        "string",
        "null"
      ]
    },
    "unit_plural": {
      "description": "null: the unit plus s",
      "type": [
        "string",
        "null"
      ]
    },
    "unit_cents": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        {
          "type": "null"
        }
      ],
      "description": "null: no price yet"
    },
    "price_set": {
      "type": "boolean"
    },
    "price": {
      "type": [
        "string",
        "null"
      ]
    },
    "currency": {
      "type": "string"
    },
    "billing": {
      "type": "string",
      "enum": [
        "one_time",
        "yearly",
        "semiannual",
        "quarterly",
        "monthly",
        "weekly"
      ]
    },
    "min_qty": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "max_qty": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "billed_as_used": {
      "type": "boolean",
      "description": "A rate per unit_label, with no quantity; never in a total"
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "archived"
      ]
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "category",
    "description",
    "includes",
    "unit_label",
    "unit_plural",
    "unit_cents",
    "price_set",
    "price",
    "currency",
    "billing",
    "min_qty",
    "max_qty",
    "billed_as_used",
    "status",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

Proposal

{
  "type": "object",
  "properties": {
    "proposal": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "version": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "viewed",
            "signed",
            "declined",
            "expired",
            "revoked",
            "superseded"
          ]
        },
        "client_id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "template_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "campaign_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "offer_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "packet_id": {
          "description": "The walkthrough it was sent in; present only when it's part of a walkthrough",
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "build": {
          "description": "Drafts only",
          "anyOf": [
            {
              "$ref": "#/components/schemas/PricedBuild"
            },
            {
              "type": "null"
            }
          ]
        },
        "preview": {
          "description": "Drafts only",
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "preview_sha256": {
                  "type": "string"
                },
                "previewed_at": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh_until": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh": {
                  "type": "boolean"
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "preview_sha256",
                "previewed_at",
                "fresh_until",
                "fresh",
                "expires_at"
              ],
              "additionalProperties": false
            },
            {
              "type": "null"
            }
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "required": [
        "id",
        "version",
        "status",
        "client_id",
        "template_id",
        "campaign_id",
        "offer_id",
        "created_at",
        "updated_at"
      ],
      "additionalProperties": {}
    },
    "signature": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "signed_at": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "typed_name": {
              "type": "string"
            },
            "signer_title": {
              "description": "Signed for a business client: the signer's title; absent otherwise",
              "type": "string"
            },
            "signer_capacity": {
              "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            },
            "on_behalf_of": {
              "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
              "type": "string"
            },
            "total_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: one-time plus yearly. Use totals, which also carries amounts billed every six months, quarterly, or weekly."
            },
            "monthly_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: the monthly amount. Use totals."
            },
            "totals": {
              "description": "What the client agreed to pay: net of any discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "currency": {
              "type": "string"
            },
            "discounts": {
              "description": "Discount lines that came off, each with its kind; present only when one did (as in the webhook events, /api/docs/webhooks)",
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string"
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "kind",
                  "label",
                  "amount_cents"
                ],
                "additionalProperties": {}
              }
            },
            "listed_totals": {
              "description": "The totals before discounts; present only with discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "pdf": {
              "type": "object",
              "properties": {
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "sha256": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "ready": {
                  "type": "boolean"
                }
              },
              "required": [
                "url",
                "sha256",
                "ready"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "signed_at",
            "typed_name",
            "total_cents",
            "monthly_cents",
            "totals",
            "currency",
            "pdf"
          ],
          "additionalProperties": {}
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "proposal",
    "signature"
  ],
  "additionalProperties": false,
  "description": "A sent proposal carries the webhook's proposal block (/api/docs/webhooks) plus these ids and times; a draft carries its build and preview instead."
}

PricedBuild

{
  "type": "object",
  "properties": {
    "mode": {
      "type": "string",
      "enum": [
        "fixed",
        "choose"
      ]
    },
    "period": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string"
        },
        "label": {
          "type": "string"
        }
      },
      "required": [
        "key",
        "label"
      ],
      "additionalProperties": false
    },
    "expiry_days": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "note": {
      "type": "string"
    },
    "currency": {
      "type": "string"
    },
    "packages": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "badge": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": "string"
          },
          "total_cents": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Kept for compatibility: one-time plus yearly. Use totals, which also carries amounts billed every six months, quarterly, or weekly."
          },
          "monthly_cents": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Kept for compatibility: the monthly amount. Use totals."
          },
          "totals": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BillingTotals"
              },
              {
                "type": "null"
              }
            ],
            "description": "null while an item has no price"
          },
          "net_totals": {
            "description": "This package alone, net of the discount lines; present only with discounts",
            "$ref": "#/components/schemas/BillingTotals"
          },
          "lines": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "catalog_item_id": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "name": {
                  "type": "string"
                },
                "qty": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                "unit_cents": {
                  "anyOf": [
                    {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "amount_cents": {
                  "anyOf": [
                    {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "billing": {
                  "type": "string",
                  "enum": [
                    "one_time",
                    "yearly",
                    "semiannual",
                    "quarterly",
                    "monthly",
                    "weekly"
                  ]
                },
                "billed_as_used": {
                  "type": "boolean",
                  "description": "A rate: unit_cents per unit_label, qty and amount 0, in no total"
                },
                "unit_label": {
                  "type": "string"
                }
              },
              "required": [
                "catalog_item_id",
                "name",
                "qty",
                "unit_cents",
                "amount_cents",
                "billing",
                "billed_as_used",
                "unit_label"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "id",
          "name",
          "badge",
          "description",
          "total_cents",
          "monthly_cents",
          "totals",
          "lines"
        ],
        "additionalProperties": false
      }
    },
    "addons": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "unit_cents": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "name",
          "unit_cents"
        ],
        "additionalProperties": {}
      }
    },
    "discounts": {
      "description": "Discount lines, read-only over the API: fixed amounts taken off whatever the client chooses, each in one frequency. Absent when there are none.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "discount_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              {
                "type": "null"
              }
            ],
            "description": "null: a one-off typed in the builder"
          },
          "kind": {
            "type": "string",
            "const": "per_client"
          },
          "label": {
            "type": "string"
          },
          "amount_cents": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Positive: this much is taken off"
          },
          "billing": {
            "type": "string",
            "enum": [
              "one_time",
              "yearly",
              "semiannual",
              "quarterly",
              "monthly",
              "weekly"
            ]
          }
        },
        "required": [
          "id",
          "discount_id",
          "kind",
          "label",
          "amount_cents",
          "billing"
        ],
        "additionalProperties": false
      }
    },
    "unpriced": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Items with no price yet; preview refuses while any"
    },
    "no_unit": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Rates billed as used with no unit yet; preview refuses while any"
    }
  },
  "required": [
    "mode",
    "period",
    "expiry_days",
    "note",
    "currency",
    "packages",
    "addons",
    "unpriced",
    "no_unit"
  ],
  "additionalProperties": false
}

ProposalDetail

{
  "type": "object",
  "properties": {
    "proposal": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "version": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "viewed",
            "signed",
            "declined",
            "expired",
            "revoked",
            "superseded"
          ]
        },
        "client_id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "template_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "campaign_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "offer_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "packet_id": {
          "description": "The walkthrough it was sent in; present only when it's part of a walkthrough",
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "build": {
          "description": "Drafts only",
          "anyOf": [
            {
              "$ref": "#/components/schemas/PricedBuild"
            },
            {
              "type": "null"
            }
          ]
        },
        "preview": {
          "description": "Drafts only",
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "preview_sha256": {
                  "type": "string"
                },
                "previewed_at": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh_until": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh": {
                  "type": "boolean"
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "preview_sha256",
                "previewed_at",
                "fresh_until",
                "fresh",
                "expires_at"
              ],
              "additionalProperties": false
            },
            {
              "type": "null"
            }
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "required": [
        "id",
        "version",
        "status",
        "client_id",
        "template_id",
        "campaign_id",
        "offer_id",
        "created_at",
        "updated_at"
      ],
      "additionalProperties": {}
    },
    "signature": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "signed_at": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "typed_name": {
              "type": "string"
            },
            "signer_title": {
              "description": "Signed for a business client: the signer's title; absent otherwise",
              "type": "string"
            },
            "signer_capacity": {
              "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            },
            "on_behalf_of": {
              "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
              "type": "string"
            },
            "total_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: one-time plus yearly. Use totals, which also carries amounts billed every six months, quarterly, or weekly."
            },
            "monthly_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: the monthly amount. Use totals."
            },
            "totals": {
              "description": "What the client agreed to pay: net of any discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "currency": {
              "type": "string"
            },
            "discounts": {
              "description": "Discount lines that came off, each with its kind; present only when one did (as in the webhook events, /api/docs/webhooks)",
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string"
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "kind",
                  "label",
                  "amount_cents"
                ],
                "additionalProperties": {}
              }
            },
            "listed_totals": {
              "description": "The totals before discounts; present only with discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "pdf": {
              "type": "object",
              "properties": {
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "sha256": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "ready": {
                  "type": "boolean"
                }
              },
              "required": [
                "url",
                "sha256",
                "ready"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "signed_at",
            "typed_name",
            "total_cents",
            "monthly_cents",
            "totals",
            "currency",
            "pdf"
          ],
          "additionalProperties": {}
        },
        {
          "type": "null"
        }
      ]
    },
    "copied_people": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/CopiedPerson"
      }
    },
    "signing": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/Signing"
        },
        {
          "type": "null"
        }
      ],
      "description": "Null with one signer, the client (people with role signer make more)"
    },
    "signers": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/Signer"
      },
      "description": "Every signer, the client included; empty with one"
    }
  },
  "required": [
    "proposal",
    "signature",
    "copied_people",
    "signing",
    "signers"
  ],
  "additionalProperties": false
}

CopiedPerson

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "relationship": {
      "type": "string",
      "enum": [
        "spouse",
        "family",
        "assistant",
        "business_partner",
        "other"
      ]
    },
    "role": {
      "type": "string",
      "enum": [
        "copied",
        "signer"
      ]
    },
    "signed_copy": {
      "type": "boolean",
      "description": "They get the signed copy"
    },
    "link_sent_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ],
      "description": "When their view-only link was emailed; null if it wasn't"
    },
    "first_viewed_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "last_viewed_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "view_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "access_removed_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ],
      "description": "Staff removed their access; their link no longer works"
    }
  },
  "required": [
    "id",
    "name",
    "email",
    "relationship",
    "role",
    "signed_copy",
    "link_sent_at",
    "first_viewed_at",
    "last_viewed_at",
    "view_count",
    "access_removed_at"
  ],
  "additionalProperties": false
}

Signing

{
  "type": "object",
  "properties": {
    "rule": {
      "type": "string",
      "enum": [
        "all",
        "any"
      ],
      "description": "all: every signer signs; any: any one of them"
    },
    "order": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "any",
            "in_order"
          ]
        },
        {
          "type": "null"
        }
      ],
      "description": "With all: any order, or one after another by position"
    }
  },
  "required": [
    "rule",
    "order"
  ],
  "additionalProperties": false
}

Signer

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "position": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "client": {
      "type": "boolean",
      "description": "The client themselves"
    },
    "state": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "waiting",
            "open",
            "signed",
            "declined",
            "voided"
          ]
        },
        {
          "type": "null"
        }
      ],
      "description": "Null on a draft"
    },
    "signed_at": {
      "type": [
        "string",
        "null"
      ]
    },
    "declined_at": {
      "type": [
        "string",
        "null"
      ]
    },
    "title": {
      "description": "A business client's signer: their title, as staff entered it; absent otherwise",
      "type": "string"
    },
    "signer_title": {
      "description": "Signed for a business client: the title they confirmed; absent otherwise",
      "type": "string"
    },
    "signer_capacity": {
      "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
      "type": "string",
      "enum": [
        "power_of_attorney",
        "guardian",
        "executor",
        "personal_representative"
      ]
    },
    "on_behalf_of": {
      "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
      "type": "string"
    }
  },
  "required": [
    "name",
    "email",
    "position",
    "client",
    "state",
    "signed_at",
    "declined_at"
  ],
  "additionalProperties": false
}

CopyResent

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "relationship": {
      "type": "string",
      "enum": [
        "spouse",
        "family",
        "assistant",
        "business_partner",
        "other"
      ]
    },
    "role": {
      "type": "string",
      "enum": [
        "copied",
        "signer"
      ]
    },
    "signed_copy": {
      "type": "boolean",
      "description": "They get the signed copy"
    },
    "link_sent_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ],
      "description": "When their view-only link was emailed; null if it wasn't"
    },
    "first_viewed_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "last_viewed_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "view_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "access_removed_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ],
      "description": "Staff removed their access; their link no longer works"
    },
    "new_link": {
      "type": "boolean",
      "description": "A new link was made (the earlier one stopped); false when their link was reused"
    }
  },
  "required": [
    "id",
    "name",
    "email",
    "relationship",
    "role",
    "signed_copy",
    "link_sent_at",
    "first_viewed_at",
    "last_viewed_at",
    "view_count",
    "access_removed_at",
    "new_link"
  ],
  "additionalProperties": false
}

Preview

{
  "type": "object",
  "properties": {
    "preview_sha256": {
      "type": "string"
    },
    "previewed_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "fresh_until": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "fresh": {
      "type": "boolean"
    },
    "expires_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "totals": {
      "$ref": "#/components/schemas/PricedBuild"
    },
    "document_url": {
      "type": "string",
      "description": "The rendered document; needs your API key, like the PDF"
    }
  },
  "required": [
    "preview_sha256",
    "previewed_at",
    "fresh_until",
    "fresh",
    "expires_at",
    "totals",
    "document_url"
  ],
  "additionalProperties": false
}

Sent

{
  "type": "object",
  "properties": {
    "proposal": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "version": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "viewed",
            "signed",
            "declined",
            "expired",
            "revoked",
            "superseded"
          ]
        },
        "client_id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "template_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "campaign_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "offer_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "packet_id": {
          "description": "The walkthrough it was sent in; present only when it's part of a walkthrough",
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "build": {
          "description": "Drafts only",
          "anyOf": [
            {
              "$ref": "#/components/schemas/PricedBuild"
            },
            {
              "type": "null"
            }
          ]
        },
        "preview": {
          "description": "Drafts only",
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "preview_sha256": {
                  "type": "string"
                },
                "previewed_at": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh_until": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh": {
                  "type": "boolean"
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "preview_sha256",
                "previewed_at",
                "fresh_until",
                "fresh",
                "expires_at"
              ],
              "additionalProperties": false
            },
            {
              "type": "null"
            }
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "required": [
        "id",
        "version",
        "status",
        "client_id",
        "template_id",
        "campaign_id",
        "offer_id",
        "created_at",
        "updated_at"
      ],
      "additionalProperties": {}
    },
    "signature": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "signed_at": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "typed_name": {
              "type": "string"
            },
            "signer_title": {
              "description": "Signed for a business client: the signer's title; absent otherwise",
              "type": "string"
            },
            "signer_capacity": {
              "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            },
            "on_behalf_of": {
              "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
              "type": "string"
            },
            "total_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: one-time plus yearly. Use totals, which also carries amounts billed every six months, quarterly, or weekly."
            },
            "monthly_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: the monthly amount. Use totals."
            },
            "totals": {
              "description": "What the client agreed to pay: net of any discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "currency": {
              "type": "string"
            },
            "discounts": {
              "description": "Discount lines that came off, each with its kind; present only when one did (as in the webhook events, /api/docs/webhooks)",
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string"
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "kind",
                  "label",
                  "amount_cents"
                ],
                "additionalProperties": {}
              }
            },
            "listed_totals": {
              "description": "The totals before discounts; present only with discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "pdf": {
              "type": "object",
              "properties": {
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "sha256": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "ready": {
                  "type": "boolean"
                }
              },
              "required": [
                "url",
                "sha256",
                "ready"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "signed_at",
            "typed_name",
            "total_cents",
            "monthly_cents",
            "totals",
            "currency",
            "pdf"
          ],
          "additionalProperties": {}
        },
        {
          "type": "null"
        }
      ]
    },
    "emailed": {
      "type": "boolean"
    },
    "credits": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "left": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "overage_used": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "overage_room": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "left",
            "overage_used",
            "overage_room"
          ],
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ],
      "description": "null before credits start for the business"
    }
  },
  "required": [
    "proposal",
    "signature",
    "emailed",
    "credits"
  ],
  "additionalProperties": false
}

Withdrawn

{
  "type": "object",
  "properties": {
    "proposal": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "version": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "viewed",
            "signed",
            "declined",
            "expired",
            "revoked",
            "superseded"
          ]
        },
        "client_id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "template_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "campaign_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "offer_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "packet_id": {
          "description": "The walkthrough it was sent in; present only when it's part of a walkthrough",
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "build": {
          "description": "Drafts only",
          "anyOf": [
            {
              "$ref": "#/components/schemas/PricedBuild"
            },
            {
              "type": "null"
            }
          ]
        },
        "preview": {
          "description": "Drafts only",
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "preview_sha256": {
                  "type": "string"
                },
                "previewed_at": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh_until": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh": {
                  "type": "boolean"
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "preview_sha256",
                "previewed_at",
                "fresh_until",
                "fresh",
                "expires_at"
              ],
              "additionalProperties": false
            },
            {
              "type": "null"
            }
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "required": [
        "id",
        "version",
        "status",
        "client_id",
        "template_id",
        "campaign_id",
        "offer_id",
        "created_at",
        "updated_at"
      ],
      "additionalProperties": {}
    },
    "signature": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "signed_at": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "typed_name": {
              "type": "string"
            },
            "signer_title": {
              "description": "Signed for a business client: the signer's title; absent otherwise",
              "type": "string"
            },
            "signer_capacity": {
              "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            },
            "on_behalf_of": {
              "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
              "type": "string"
            },
            "total_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: one-time plus yearly. Use totals, which also carries amounts billed every six months, quarterly, or weekly."
            },
            "monthly_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: the monthly amount. Use totals."
            },
            "totals": {
              "description": "What the client agreed to pay: net of any discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "currency": {
              "type": "string"
            },
            "discounts": {
              "description": "Discount lines that came off, each with its kind; present only when one did (as in the webhook events, /api/docs/webhooks)",
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string"
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "kind",
                  "label",
                  "amount_cents"
                ],
                "additionalProperties": {}
              }
            },
            "listed_totals": {
              "description": "The totals before discounts; present only with discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "pdf": {
              "type": "object",
              "properties": {
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "sha256": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "ready": {
                  "type": "boolean"
                }
              },
              "required": [
                "url",
                "sha256",
                "ready"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "signed_at",
            "typed_name",
            "total_cents",
            "monthly_cents",
            "totals",
            "currency",
            "pdf"
          ],
          "additionalProperties": {}
        },
        {
          "type": "null"
        }
      ]
    },
    "client_emailed": {
      "type": "boolean"
    },
    "credits": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "left": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "overage_used": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "overage_room": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "left",
            "overage_used",
            "overage_room"
          ],
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ],
      "description": "null before credits start for the business"
    }
  },
  "required": [
    "proposal",
    "signature",
    "client_emailed",
    "credits"
  ],
  "additionalProperties": false
}

Resent

{
  "type": "object",
  "properties": {
    "proposal": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "version": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "viewed",
            "signed",
            "declined",
            "expired",
            "revoked",
            "superseded"
          ]
        },
        "client_id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "template_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "campaign_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "offer_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "packet_id": {
          "description": "The walkthrough it was sent in; present only when it's part of a walkthrough",
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "build": {
          "description": "Drafts only",
          "anyOf": [
            {
              "$ref": "#/components/schemas/PricedBuild"
            },
            {
              "type": "null"
            }
          ]
        },
        "preview": {
          "description": "Drafts only",
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "preview_sha256": {
                  "type": "string"
                },
                "previewed_at": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh_until": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh": {
                  "type": "boolean"
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "preview_sha256",
                "previewed_at",
                "fresh_until",
                "fresh",
                "expires_at"
              ],
              "additionalProperties": false
            },
            {
              "type": "null"
            }
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "required": [
        "id",
        "version",
        "status",
        "client_id",
        "template_id",
        "campaign_id",
        "offer_id",
        "created_at",
        "updated_at"
      ],
      "additionalProperties": {}
    },
    "signature": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "signed_at": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "typed_name": {
              "type": "string"
            },
            "signer_title": {
              "description": "Signed for a business client: the signer's title; absent otherwise",
              "type": "string"
            },
            "signer_capacity": {
              "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            },
            "on_behalf_of": {
              "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
              "type": "string"
            },
            "total_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: one-time plus yearly. Use totals, which also carries amounts billed every six months, quarterly, or weekly."
            },
            "monthly_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: the monthly amount. Use totals."
            },
            "totals": {
              "description": "What the client agreed to pay: net of any discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "currency": {
              "type": "string"
            },
            "discounts": {
              "description": "Discount lines that came off, each with its kind; present only when one did (as in the webhook events, /api/docs/webhooks)",
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string"
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "kind",
                  "label",
                  "amount_cents"
                ],
                "additionalProperties": {}
              }
            },
            "listed_totals": {
              "description": "The totals before discounts; present only with discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "pdf": {
              "type": "object",
              "properties": {
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "sha256": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "ready": {
                  "type": "boolean"
                }
              },
              "required": [
                "url",
                "sha256",
                "ready"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "signed_at",
            "typed_name",
            "total_cents",
            "monthly_cents",
            "totals",
            "currency",
            "pdf"
          ],
          "additionalProperties": {}
        },
        {
          "type": "null"
        }
      ]
    },
    "emailed": {
      "type": "boolean",
      "description": "false when the business has no email sender: proposal.sent tells its automation"
    },
    "expires_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "proposal",
    "signature",
    "emailed",
    "expires_at"
  ],
  "additionalProperties": false
}

Extended

{
  "type": "object",
  "properties": {
    "proposal": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "version": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "viewed",
            "signed",
            "declined",
            "expired",
            "revoked",
            "superseded"
          ]
        },
        "client_id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "template_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "campaign_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "offer_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "packet_id": {
          "description": "The walkthrough it was sent in; present only when it's part of a walkthrough",
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "build": {
          "description": "Drafts only",
          "anyOf": [
            {
              "$ref": "#/components/schemas/PricedBuild"
            },
            {
              "type": "null"
            }
          ]
        },
        "preview": {
          "description": "Drafts only",
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "preview_sha256": {
                  "type": "string"
                },
                "previewed_at": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh_until": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh": {
                  "type": "boolean"
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "preview_sha256",
                "previewed_at",
                "fresh_until",
                "fresh",
                "expires_at"
              ],
              "additionalProperties": false
            },
            {
              "type": "null"
            }
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "required": [
        "id",
        "version",
        "status",
        "client_id",
        "template_id",
        "campaign_id",
        "offer_id",
        "created_at",
        "updated_at"
      ],
      "additionalProperties": {}
    },
    "signature": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "signed_at": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "typed_name": {
              "type": "string"
            },
            "signer_title": {
              "description": "Signed for a business client: the signer's title; absent otherwise",
              "type": "string"
            },
            "signer_capacity": {
              "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            },
            "on_behalf_of": {
              "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
              "type": "string"
            },
            "total_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: one-time plus yearly. Use totals, which also carries amounts billed every six months, quarterly, or weekly."
            },
            "monthly_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: the monthly amount. Use totals."
            },
            "totals": {
              "description": "What the client agreed to pay: net of any discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "currency": {
              "type": "string"
            },
            "discounts": {
              "description": "Discount lines that came off, each with its kind; present only when one did (as in the webhook events, /api/docs/webhooks)",
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string"
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "kind",
                  "label",
                  "amount_cents"
                ],
                "additionalProperties": {}
              }
            },
            "listed_totals": {
              "description": "The totals before discounts; present only with discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "pdf": {
              "type": "object",
              "properties": {
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "sha256": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "ready": {
                  "type": "boolean"
                }
              },
              "required": [
                "url",
                "sha256",
                "ready"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "signed_at",
            "typed_name",
            "total_cents",
            "monthly_cents",
            "totals",
            "currency",
            "pdf"
          ],
          "additionalProperties": {}
        },
        {
          "type": "null"
        }
      ]
    },
    "reopened": {
      "type": "boolean",
      "description": "true when it had expired and extending it reopened it"
    },
    "emailed": {
      "type": "boolean",
      "description": "true when an email with the new date was queued (or held while email is paused); false when notify_client was false or there's no email sender"
    }
  },
  "required": [
    "proposal",
    "signature",
    "reopened",
    "emailed"
  ],
  "additionalProperties": false,
  "description": "The proposal as it is now: its proposal block's expires_at is the new deadline and original_expires_at the respond-by date the document printed."
}

Revision

{
  "type": "object",
  "properties": {
    "proposal": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "version": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "sent",
            "viewed",
            "signed",
            "declined",
            "expired",
            "revoked",
            "superseded"
          ]
        },
        "client_id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "template_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "campaign_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "offer_id": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "packet_id": {
          "description": "The walkthrough it was sent in; present only when it's part of a walkthrough",
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "build": {
          "description": "Drafts only",
          "anyOf": [
            {
              "$ref": "#/components/schemas/PricedBuild"
            },
            {
              "type": "null"
            }
          ]
        },
        "preview": {
          "description": "Drafts only",
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "preview_sha256": {
                  "type": "string"
                },
                "previewed_at": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh_until": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                "fresh": {
                  "type": "boolean"
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "preview_sha256",
                "previewed_at",
                "fresh_until",
                "fresh",
                "expires_at"
              ],
              "additionalProperties": false
            },
            {
              "type": "null"
            }
          ]
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "required": [
        "id",
        "version",
        "status",
        "client_id",
        "template_id",
        "campaign_id",
        "offer_id",
        "created_at",
        "updated_at"
      ],
      "additionalProperties": {}
    },
    "signature": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "signed_at": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "typed_name": {
              "type": "string"
            },
            "signer_title": {
              "description": "Signed for a business client: the signer's title; absent otherwise",
              "type": "string"
            },
            "signer_capacity": {
              "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            },
            "on_behalf_of": {
              "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
              "type": "string"
            },
            "total_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: one-time plus yearly. Use totals, which also carries amounts billed every six months, quarterly, or weekly."
            },
            "monthly_cents": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991,
              "description": "Kept for compatibility: the monthly amount. Use totals."
            },
            "totals": {
              "description": "What the client agreed to pay: net of any discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "currency": {
              "type": "string"
            },
            "discounts": {
              "description": "Discount lines that came off, each with its kind; present only when one did (as in the webhook events, /api/docs/webhooks)",
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string"
                  },
                  "amount_cents": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "kind",
                  "label",
                  "amount_cents"
                ],
                "additionalProperties": {}
              }
            },
            "listed_totals": {
              "description": "The totals before discounts; present only with discounts",
              "$ref": "#/components/schemas/BillingTotals"
            },
            "pdf": {
              "type": "object",
              "properties": {
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "sha256": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "ready": {
                  "type": "boolean"
                }
              },
              "required": [
                "url",
                "sha256",
                "ready"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "signed_at",
            "typed_name",
            "total_cents",
            "monthly_cents",
            "totals",
            "currency",
            "pdf"
          ],
          "additionalProperties": {}
        },
        {
          "type": "null"
        }
      ]
    },
    "template_changed": {
      "type": "boolean"
    }
  },
  "required": [
    "proposal",
    "signature",
    "template_changed"
  ],
  "additionalProperties": false
}

Document

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "kind": {
      "type": "string",
      "enum": [
        "agreement",
        "consent"
      ]
    },
    "version": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "status": {
      "type": "string",
      "enum": [
        "draft",
        "sent",
        "viewed",
        "signed",
        "declined",
        "expired",
        "revoked",
        "superseded"
      ]
    },
    "template": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "name": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "name"
      ],
      "additionalProperties": false
    },
    "client": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "external_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "display_name": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "external_id",
        "display_name"
      ],
      "additionalProperties": false
    },
    "campaign_id": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    },
    "packet_id": {
      "description": "The walkthrough it was sent in; present only when it's part of a walkthrough",
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "supersedes_id": {
      "anyOf": [
        {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        {
          "type": "null"
        }
      ]
    },
    "sent_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "expires_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ],
      "description": "When it ends: the deadline after any extension"
    },
    "original_expires_at": {
      "description": "The respond-by date the document shows; present only once the deadline was extended",
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "resolved_at": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        {
          "type": "null"
        }
      ]
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "signers": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "position": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "client": {
            "type": "boolean",
            "description": "The client themselves"
          },
          "name": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "waiting",
              "open",
              "signed",
              "declined",
              "voided"
            ]
          },
          "signed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ]
          },
          "declined_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ]
          },
          "signer_title": {
            "description": "Signed for a business client: the title they confirmed; absent otherwise",
            "type": "string"
          },
          "signer_capacity": {
            "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
            "type": "string",
            "enum": [
              "power_of_attorney",
              "guardian",
              "executor",
              "personal_representative"
            ]
          },
          "on_behalf_of": {
            "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
            "type": "string"
          }
        },
        "required": [
          "position",
          "client",
          "name",
          "state",
          "signed_at",
          "declined_at"
        ],
        "additionalProperties": false
      },
      "description": "Every signer, the client included; empty with one. Never an email or a link."
    },
    "signature": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "signed_at": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "typed_name": {
              "type": "string"
            },
            "signer_title": {
              "description": "Signed for a business client: the signer's title; absent otherwise",
              "type": "string"
            },
            "signer_capacity": {
              "description": "Signed by a represented client's representative: how they signed for the client; absent otherwise",
              "type": "string",
              "enum": [
                "power_of_attorney",
                "guardian",
                "executor",
                "personal_representative"
              ]
            },
            "on_behalf_of": {
              "description": "Signed for a business client, or by a represented client's representative: who for; absent otherwise",
              "type": "string"
            },
            "signing_method": {
              "type": "string"
            },
            "consents": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "version": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "id",
                  "title",
                  "version"
                ],
                "additionalProperties": false
              },
              "description": "The business's consent documents agreed to on it"
            }
          },
          "required": [
            "signed_at",
            "typed_name",
            "signing_method",
            "consents"
          ],
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ],
      "description": "When it's signed"
    },
    "pdf_ready": {
      "type": "boolean"
    }
  },
  "required": [
    "id",
    "kind",
    "version",
    "status",
    "template",
    "client",
    "campaign_id",
    "supersedes_id",
    "sent_at",
    "expires_at",
    "resolved_at",
    "created_at",
    "updated_at",
    "signers",
    "signature",
    "pdf_ready"
  ],
  "additionalProperties": false,
  "description": "An agreement or a consent sent on its own. It has no price."
}

Event

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "evt_ followed by 32 hex characters, as in the webhook"
    },
    "type": {
      "type": "string"
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "tenant": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
        },
        "slug": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "slug"
      ],
      "additionalProperties": false
    },
    "data": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {},
      "description": "The webhook payload. signing_url and resume_url are null (with redacted: true) unless the key has proposals:links."
    },
    "delivery": {
      "type": "string",
      "enum": [
        "delivered",
        "due",
        "failed",
        "off"
      ]
    }
  },
  "required": [
    "id",
    "type",
    "created_at",
    "tenant",
    "data",
    "delivery"
  ],
  "additionalProperties": false
}