> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firma.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# FAQ

> Answers to the questions Firma.dev support receives most often, with links to the guide that covers each topic in depth.

## Getting started & account

<AccordionGroup>
  <Accordion title="Where do I find my live/test API keys, and can I get them via API?">
    Yes. Your account's main key is on the dashboard's **Dashboard** page; each workspace's own keys are on that workspace's **Info** tab, and there's no separate "Settings > API Keys" page. You can also fetch them via the API. Only the workspace **Owner** can generate or regenerate keys from the dashboard.

    **See:** [API Authentication & JWT Tokens](/guides/authentication#test-mode-live-vs-test-keys), [Complete Setup Guide](/guides/complete-setup-guide#create-your-account-get-your-api-key)
  </Accordion>

  <Accordion title="Is there a free trial or sandbox? What does test mode cost?">
    No, Firma.dev doesn't offer a separate trial period or sandbox account, and test mode doesn't cost anything to use. Test-key requests are still subject to the normal API rate limits, same as live requests, and the embeddable editors and hosted signing page behave identically in test mode and live mode.

    **See:** [API Authentication & JWT Tokens](/guides/authentication#test-mode-live-vs-test-keys), [Complete Setup Guide](/guides/complete-setup-guide#start-in-test-mode)
  </Accordion>

  <Accordion title="Do I need to sign a contract or book a demo before using Firma.dev?">
    No. Signing up is self-serve, with no contract and no sales demo required: create an account, accept the standard terms of service at signup, and get your API key from the dashboard. Pricing has no minimums, no contracts, and no monthly fees. You can integrate directly from the docs, the MCP server, or one of Firma.dev's AI-coding-tool integration guides (Claude Code, Cursor, ChatGPT, and others) without ever talking to sales.
  </Accordion>

  <Accordion title="What is the difference between the Owner, Admin, and View Only roles?">
    Firma.dev has three account roles: **Owner**, **Admin**, and **View Only**.

    * **Owner**: the only role that can manage billing, create, delete, or rename workspaces, and generate or regenerate API keys.
    * **Owner and Admin**: can both manage webhooks, custom domains, and workspace or company settings, invite or remove users (though an Admin can't create or promote another Owner), and create signing requests.
    * **View Only**: can only read and copy existing data.

    A few workspace toggle settings, like OTP verification or the signature frame display, are Owner-only on the backend. The UI doesn't yet block Admin or View Only users from toggling them, so a non-Owner may see a "saved" confirmation even though the change didn't apply. If a setting doesn't seem to stick, have an Owner make the change.
  </Accordion>

  <Accordion title="Why didn't a new team member receive an invitation email?">
    By design, adding a team member creates their account immediately instead of sending an email invitation: the new user's temporary password is shown once on screen at creation time, not emailed. Share that password with them so they can log in, then they'll be prompted to set their own password on first login. If the temporary password is lost before it's used, use **Forgot password** on the login page to reset it.
  </Accordion>

  <Accordion title="How do I change my account email, or merge/delete an account?">
    Change your **login email** from the **My Profile** dialog (open it from your avatar or "My Profile" in the sidebar); this triggers a standard email-change confirmation flow to the new address. The Account page's Company Information tab also has an "Email" field, but that's a separate company-level billing/notification contact address: changing it does not affect how you log in. Signing up with a different email always creates a separate account; Firma.dev has no self-serve way to merge accounts. To merge accounts or delete your account entirely, contact support.
  </Accordion>

  <Accordion title="Why is my password reset link expired, or the email missing?">
    Password reset links are single-use and time-limited; once a link has been opened once (or opened automatically on your behalf), a second click shows as expired or invalid, and you'll need to request a fresh one from **Forgot password**. A common cause of a link being consumed before you click it is a corporate email security scanner that automatically opens links in incoming mail; a shared or alias mailbox can also delay or filter the message. Make sure you're requesting the reset for the exact email address your account is registered under, and contact support if the problem continues.
  </Accordion>

  <Accordion title="How does integration with Firma.dev work?">
    You integrate through Firma.dev's REST API, optionally paired with its embeddable editors. Firma.dev also provides a TypeScript SDK, and publishes step-by-step guides for platforms such as n8n, Supabase, and Lovable, beyond the AI coding-tool clients its MCP servers cover.

    **See:** [Complete Setup Guide](/guides/complete-setup-guide), [Embeddable signing](/guides/embeddable-signing), [MCP Integration](/guides/mcp)
  </Accordion>

  <Accordion title="What can I do with the Firma.dev API?">
    The API covers the full e-signature workflow, from creating a signing request to receiving a signed, sealed document. Fields can also be placed with anchor tags, with conditional and required-field rules, email OTP verification, and full control over every email Firma.dev sends. Completed documents are sealed as PAdES-B-LTA PDFs with a completion certificate, and each workspace isolates a customer's branding, sending domains, and email templates.

    **See:** [Sending a signing request](/guides/sending-signing-request), [Webhooks](/guides/webhooks), [Audit Trail](/guides/audit-trail)
  </Accordion>
</AccordionGroup>

## Pricing & billing

<AccordionGroup>
  <Accordion title="What does one credit cover, and when is it charged or refunded?">
    One credit covers a single signing request, charged when you send it and never refunded afterward. One credit equals one signing request (envelope), regardless of how many signers or documents it contains. It's deducted when the request is sent, right after the signing emails go out and before the request is marked sent, not when signers finish. Credits aren't refunded if a signer declines or the request expires, and no credit is charged if send validation fails or the email itself fails to send.

    **See:** [Complete Setup Guide](/guides/complete-setup-guide#monitor-usage-check-credits)
  </Accordion>

  <Accordion title="How much does Firma.dev cost, and are there subscriptions or minimums?">
    Firma.dev is pay-as-you-go, with no subscriptions, minimums, or seat fees. Credits don't expire. Accounts created before Firma.dev's most recent price change, or signed up through another customer's referral code, keep that earlier, lower per-credit rate for the life of the account. A referral code doesn't gate access (anyone can sign up freely), but it earns both parties bonus credits on the referred company's first purchase.

    **See:** [Complete Setup Guide](/guides/complete-setup-guide#monitor-usage-check-credits)
  </Accordion>

  <Accordion title="Where do I download invoices, and how do I add my company name and VAT number?">
    Download invoices from **Account > Credits & Billing**, and add your company details before checkout. Enter your company name, billing address, and VAT number in the **Add tax number** step of the Paddle checkout before you pay. To correct an already-issued invoice, email [support@firma.dev](mailto:support@firma.dev) with the invoice number, company name, billing address, and VAT ID. It's reissued and shown via the same View link.

    **See:** [Platform Updates: Invoice downloads](/guides/platform-updates#invoice-downloads)
  </Accordion>

  <Accordion title="Why does adding credits fail with a Paddle.js error?">
    This is almost always caused by an ad blocker, privacy extension, or corporate network filter blocking Paddle's checkout script from loading. Firma.dev surfaces this as "Failed to load payment system: Failed to load Paddle.js." Try disabling the blocker for the site, or open the page in a private/incognito window or a different browser. If a purchase seems to have failed partway through, check **Account > Credits & Billing > Transaction History** to confirm whether it actually went through before retrying, so you don't pay twice.
  </Accordion>

  <Accordion title="How do I handle high volume, and is there auto-recharge?">
    Yes, auto-recharge is available. Buy credits any time from **Account > Credits & Billing**, and turn on **Auto-Recharge** in that same tab to automatically purchase a set credit bundle whenever your balance drops below a threshold you choose. There are no volume-based discount tiers currently; every credit bundle is priced at your account's standard per-credit rate regardless of how much you buy at once.

    **See:** [Complete Setup Guide](/guides/complete-setup-guide#monitor-usage-check-credits)
  </Accordion>
</AccordionGroup>

## Sending signing requests

<AccordionGroup>
  <Accordion title="Why weren't any emails sent after I created a signing request via the API?">
    `POST /signing-requests` only creates a draft. It never sends an email on its own, regardless of your `settings`.

    **See:** [Sending a signing request: Create vs. create-and-send](/guides/sending-signing-request#create-vs-create-and-send)
  </Accordion>

  <Accordion title="Can I send signing links through my own email system instead of Firma.dev's?">
    Yes, you can suppress Firma.dev's own signing and completion emails and send the signing link through your own system instead.

    * `settings.send_signing_email: false`: suppresses Firma.dev's notification email while the request still sends, and it works whether you call `/send` or `create-and-send`.
    * `settings.send_finish_email: false`: turns off the completion email the same way.
    * `reminders`: array you provide on create that controls reminder emails, with document-based requests getting none by default and template-based requests inheriting the template's reminders unless you override it.

    **See:** [Sending a signing request: The send\_signing\_email flag](/guides/sending-signing-request#the-sendsigningemail-flag) and [Sending a signing request: Embedding the signing view](/guides/sending-signing-request#embedding-the-signing-view)
  </Accordion>

  <Accordion title="What's the correct API base URL, and why do documented paths 404?">
    The correct base URL is:

    ```text theme={null}
    https://api.firma.dev/functions/v1/signing-request-api
    ```

    Append the resource path after it, e.g. `.../signing-requests`. 404s often come from two sources:

    * `https://api.firma.dev/api/v1`: a second, "Planned" server listed in the public OpenAPI spec for a future API shape, not a real endpoint, so a generated client pointed at it 404s on every call.
    * `POST /signing-requests`: the actual endpoint behind the "Create Signing Request" reference page, not a `/create-signing-request` route as the title might suggest.

    **See:** [Authentication: Code Examples](/guides/authentication#code-examples)
  </Accordion>

  <Accordion title="What does a valid create-signing-request payload look like (recipients, fields, positions)?">
    A valid payload has a `recipients` list and a `fields` list; each field points at a recipient and a position on the page.

    Each recipient needs `first_name`, `email`, and `designation` (`Signer`, `Approver`, or `CC`). `last_name` and `order` are optional.

    Each field needs:

    * `type`: one of the supported field types, which also include `radio_buttons`, `text_area`, `url`, `file`, and `stamp`.
    * `page_number`: the page the field appears on.
    * `position`: `x`, `y`, `width`, `height` as percentages of the page, not pixels.
    * `recipient_id`: the recipient the field belongs to.

    To reference a recipient you haven't created yet, give it a temporary `id` starting with `temp_` (for example `temp_alice`) and set `recipient_id` on the field to the same value. The API maps it to a real UUID and never returns temp IDs.

    There's no top-level `metadata` property. Use each recipient's `custom_fields` object instead.

    **See:** [Sending a signing request: Recipient Schema](/guides/sending-signing-request#recipient-schema-required-fields) and [Sending a signing request: Field types](/guides/sending-signing-request#field-types)
  </Accordion>

  <Accordion title="What's the maximum document size, and how do I upload large files?">
    The maximum document size is 50MB (52,428,800 bytes). Upload large files with the two-step process:

    * `POST /documents`: uploads the file and returns a presigned `upload_url`.
    * `PUT`: send the file to that `upload_url`.
    * `document_id`: pass this when you create the signing request.

    Keep inline base64 in `document` under about 5MB, or the request can fail with a `502`. The MCP server has no upload tool, so large files go through the REST API.
  </Accordion>

  <Accordion title="Does Firma.dev support DOCX, and why does DOCX conversion sometimes fail?">
    Yes, Firma.dev supports DOCX and converts it to PDF automatically on the server before the signing request is created.

    * `POST /signing-requests`: accepts a DOCX file when you create a signing request directly.
    * `POST /documents`: accepts a DOCX file when you upload a document separately.

    That converter only renders text, headings, lists, and tables. It drops any images in the DOCX entirely, and it only loads a Latin/Cyrillic-style font set, so text in right-to-left scripts like Hebrew or Arabic can come out with missing glyphs or misrendered.

    If your document has images or non-Latin script you need preserved exactly, export it to PDF yourself first (e.g. LibreOffice, or Google Docs > File > Download > PDF) and send the PDF instead of the DOCX.
  </Accordion>

  <Accordion title="Why do I get duplicate signing requests, and is there an idempotency key?">
    No. The write endpoints (`create`, `create-and-send`, `send`, `resend`) have no `Idempotency-Key` header.

    An auto-retried `create` or `create-and-send` call can create a duplicate, separately billed, legally binding signing request. Calling `/send` again on an already-sent request returns an error instead of duplicating.

    To avoid duplicates, store the `id` returned by the first call and check for it, or query existing requests, before retrying.

    **See:** [n8n integration: Other common operations](/guides/n8n-integration#other-common-operations)
  </Accordion>

  <Accordion title="Can I change a recipient's email after sending, or cancel silently?">
    No, you can't edit a recipient's email after sending. Cancel and recreate the request instead.

    You can cancel silently:

    * `POST /signing-requests/{id}/cancel`: the endpoint to call to cancel a request.
    * `notify_signers: false`: a parameter on that cancel call itself, not a creation-time setting, that suppresses the signer notification.
    * `send_cancellation_email`: a workspace setting that must also be enabled for a cancellation email to be sent at all.

    **See:** [Signing patterns: Error handling: 409 ALREADY\_SENT](/guides/signing-patterns#error-handling-409-alreadysent)
  </Accordion>

  <Accordion title="Can a signing request include multiple documents, or swap a template's document?">
    No, a signing request has exactly one source document.

    You provide exactly one of:

    * `document`: inline base64 content.
    * `document_id`: the ID returned from a `POST` request to `/documents`.
    * `template_id`: an existing template's ID.

    These are mutually exclusive, so to combine several files into one signer flow, merge them into a single PDF yourself before creating the request.

    For templates specifically, you don't need to recreate a template to update its underlying file. `POST` to `/templates/{id}/replace-document` swaps a template's PDF while preserving all existing field placements. The replacement must have the same page count and matching page dimensions (within 1pt) as the original, so it updates content on the existing layout rather than attaching an unrelated document.
  </Accordion>

  <Accordion title="How do I download the signed PDF and certificate via the API?">
    `GET /signing-requests/{id}/download` returns the signed PDF as a pre-signed URL.

    It returns a single, short-lived pre-signed `download_url`, valid until the `expires_at` timestamp, for the final PDF. For a finished request, that one PDF already has the completion certificate and audit-trail pages appended to the signed document, and there's no separate certificate-only download URL from this endpoint.

    Calling this endpoint behaves differently depending on the signing request's state:

    * `409`: returned if you call it before the request has been sent.
    * `allow_partial_download`: when enabled, lets you get a partial-progress snapshot while signing is still in progress.
    * `503`: returned with a `Retry-After` header while a partial-progress snapshot is still being generated.
  </Accordion>

  <Accordion title="Can I retrieve a signer's signature image or uploaded files via the API?">
    Yes, you can retrieve a signer's signature image and any files they uploaded through the API.

    * `GET /signing-requests/{id}/signers/{signer_id}/signature`: returns the adopted signature as a `data:image/png;base64,...` data URI.
    * `GET /signing-requests/{id}/signers/{signer_id}/initials`: returns the adopted initials the same way.
    * `GET /signing-requests/{id}/signers/{signer_id}/stamps/{field_id}`: returns a stamp image for the given `field_id`, since stamps are per-field.
    * `GET /signing-requests/{id}/signers/{signer_id}/files/{field_id}`: returns a pre-signed download URL, valid for 300 seconds, for a file uploaded to a `file`-type field, not the file bytes directly.
    * `GET /signing-requests/{id}/fields`: filter to `type=file` to find the `field_id` for an uploaded file.

    Uploaded files are never embedded into the final signed PDF or certificate; they only exist as retrievable attachments through these endpoints.
  </Accordion>

  <Accordion title="How do I read field values back by variable name after signing?">
    `GET /signing-requests/{id}/fields` returns every field of the request; read each entry's `value` property for the resolved value and match on `variable_name`.

    **See:** [Field Prefilling: Reading field values back](/guides/field-prefilling#reading-field-values-back)
  </Accordion>
</AccordionGroup>

## Templates / fields / anchor tags

<AccordionGroup>
  <Accordion title="How are field x/y/width/height interpreted?">
    `x`, `y`, `width`, and `height` are percentages of the page, not pixels. The origin is the top-left corner and `y` grows downward.

    A manually specified field returns a `400` error when `x+width>100` or `y+height>100`. Fields placed by anchor tags are clamped back onto the page instead.
  </Accordion>

  <Accordion title="How do anchor tags work, and which field types do they support?">
    Place literal marker text in the document and pass an `anchor_tags` array on a document-based create request, up to 100 tags per request.

    Anchor tags accept every field type, and also `dropdown_options`, `format_rules`, `multi_group_id`, and `conditions`.
  </Accordion>

  <Accordion title="Why isn't anchor text removed, or why does the field look offset?">
    `remove_anchor_text` makes the matched text invisible in the PDF's content stream rather than deleted.

    It can fail on embedded/subset (CID) fonts or when the marker text is split across separate PDF text-show operators. When that happens, the system automatically draws a white box over only the matched marker area, even without `add_white_background` set.
  </Accordion>

  <Accordion title="What does 'no glyph advances for font' mean?">
    This error means the anchor marker's text sat inside a PDF Form XObject or transparency group that was not replayed when reading glyph positions.

    This typically happens in HTML-to-PDF documents, where a Chromium print pipeline wraps an element with CSS `opacity` below 1, or a `transform`, inside a transparency-group Form XObject.

    The extractor replays text inside form and group contexts (annotation appearance streams excluded), so anchors placed there are found.

    If it recurs, the anchor is likely in a malformed or unusual font/geometry construct. Re-export the source PDF with standard font encoding.
  </Accordion>

  <Accordion title="How do I prefill fields, and can the signer still edit the value?">
    Set `format_rules.prefilledData` on a field to auto-fill and lock it from recipient data.

    The signer can still edit the value if you also set `format_rules.prefilledEditable` to `true`.

    This works the same way on anchor-tag-placed fields, since anchor tags accept `format_rules` too.
  </Accordion>

  <Accordion title="Why does field text shrink or get cut off, and can I set a font size?">
    Text fields automatically shrink to fit the field's box when a value overflows, down to a default floor of 8px.

    Set `format_rules.fontSize` for an explicit starting size instead. If text is still cut off, enlarge the field or switch to a `textarea`.
  </Accordion>

  <Accordion title="How do I build single-select checkbox groups, and why do radio/checkbox values show as true/false?">
    Assign the same `multi_group_id` to a set of fields to link them into a group.

    * `radio_buttons`: fields sharing a `multi_group_id` form a mutually-exclusive group.
    * `checkbox`: fields sharing a `multi_group_id` form an independent group.

    A selected radio option's stored value is the literal string `"true"`.

    A `checkbox` field renders as a native checkbox input, not a custom checkmark icon.
  </Accordion>

  <Accordion title="How do conditional visibility/required rules work via the API, and why weren't they applied?">
    `visibility_conditions` and `required_conditions` are `ConditionSet` objects on a field that reference another field's `field_id` on the same recipient.

    * `GET /templates/{id}/fields`: returns both properties, even though the public OpenAPI schema omits them.

    When you create a signing request from a template (two-step flow, create-and-send, or `/duplicate`), both condition sets are copied and their `field_id` references remapped.
  </Accordion>

  <Accordion title="How do I add initials on every page, or multiple signature fields for one signer?">
    Add each field individually; there is no bulk option to place a field on every page.

    For initials on every page, add one `initial` field per page in the `fields` array, each with its own `page_number`. A single recipient can have multiple required fields of the same type, including several `signature` fields.
  </Accordion>

  <Accordion title="How do I auto-fill the signing date, and what timezone does it use?">
    Use a `date` field to auto-fill the signing date.

    The field renders read-only in the signing view and fills with the signer's browser-local date when they finish, not a server timezone.

    * `date_signing_default: true`: enables auto-fill; there's no separate `date_signed` type.
    * `timezone`: the workspace setting checked first for certificate timestamps, defaulting to UTC until you set it.
    * `default_timezone`: the company-level fallback checked next, also defaulting to UTC until you set it.
  </Accordion>

  <Accordion title="Are templates shared across workspaces, and how do I copy one?">
    No, templates aren't shared across workspaces, not even within the same company.

    * `POST /templates/{id}/copy`: deep-copies the template's fields, recipients, CC list, reminders, custom field definitions, and document into another workspace, using a company-level (protected) API key.
    * `workspace_id`: the target workspace you pass in the request body.
    * `POST /templates/{id}/duplicate`: creates a new signing request from the template instead, not a copy of the template.
  </Accordion>
</AccordionGroup>

## Signing experience

<AccordionGroup>
  <Accordion title="Can I redirect the signer or customize the completion page after signing?">
    Yes, you can redirect the signer or customize the completion page after signing.

    * `completion_redirect_url`: redirects the signer after they finish signing.
    * `completion_title`: customizes the completion page title, set alongside the redirect URL.
    * `completion_message`: customizes the completion page message, set alongside the redirect URL.
    * `signing.completed`: the event to listen for instead, if you embed the signing view.

    **See:** [Completion page customization (API changelog v1.34.0)](/guides/api-changelog#completion-page-customization) and [Embeddable signing - postMessage events](/guides/embeddable-signing#postmessage-events)
  </Accordion>

  <Accordion title="Can I rename or hide signing buttons, or hide the language selector?">
    You can rename signing buttons, but not hide them or the language selector.

    Relabel button text per language with `signing_button_label_overrides`, covering Finish, Approve & Finish, Next Required Field, Save & Finish Later, and the Decline dialog. The Decline button, the Save & Finish Later button, and the language selector always render and can't be hidden.

    `disable_guided_navigation` turns off auto-scroll to the next field, shown in the dashboard as "Disable Auto-Scroll".

    **See:** [Workspace settings](/guides/workspace-settings)
  </Accordion>

  <Accordion title="Can I disable or customize the terms acceptance step?">
    Yes, you can both disable it and customize its text. The terms-acceptance gate can be turned on or off per workspace, or at the company level as the default. It's on by default. The consent banner text and its linked terms page are fully customizable per language from **Workspace/Company Settings > Terms**, for each of the 14 supported languages. Anything you don't set falls back first to your company's custom text, then to Firma.dev's own built-in terms banner, which is already localized into all 14 languages.

    **See:** [Legal validity](/guides/legal-validity)
  </Accordion>

  <Accordion title="Can signers correct their name or company before signing on forwarded links?">
    Yes, signers can correct their name or company before signing on forwarded links.

    Set `identity_editable_fields` on the signing request or template, for example `name` and `company`, so the signer can edit their own details before signing. A correction dialog appears right after they accept the terms, and every edit is written to the audit trail.

    **See:** [Signing patterns - Pattern: Dynamic second signer](/guides/signing-patterns#pattern-dynamic-second-signer)
  </Accordion>

  <Accordion title="How can signers sign, can I force hand-drawn signatures, and is Cyrillic supported?">
    Signers can draw or type their signature, you can require hand-drawn signatures, and Cyrillic is supported.

    Typing auto-detects the signer's script (Latin, Cyrillic, Greek, Japanese, Korean) from their name and offers matching font styles; there's no separate upload-an-image option. Set `hand_drawn_only` to `true` on the signing request or template to remove the Type tab and require drawing.

    Firma.dev does not support signer-supplied X.509 certificates; it applies its own PAdES seal to the completed document server-side.

    **See:** [Signing patterns](/guides/signing-patterns)
  </Accordion>

  <Accordion title="The signing page is blank or black. What should the signer try?">
    Ask the signer to hard-refresh the page. If that doesn't help, open the link in a recent Chrome, Firefox, or Safari with content and ad blockers disabled, since blockers can interfere with the signing page's scripts. On iOS Safari, make sure iOS and Safari are up to date and retry; older versions could run out of memory on very large or high-resolution PDFs.
  </Accordion>

  <Accordion title="Can I set the initial zoom of the signing page?">
    Yes, add `?zoom=` to the signing URL.

    **See:** [Embeddable signing - URL parameters](/guides/embeddable-signing#url-parameters)
  </Accordion>

  <Accordion title="Why does a signing link say invalid, expired, or already signed?">
    A signing link's error message depends on the signing request's state: not yet sent, expired, already completed by that recipient, or broken, mistyped, or cancelled.

    * Not sent yet: opening the link before the sender actually sends the request shows this message.
    * Expired: the request's `expiration_hours` window, measured from when it was sent, has passed; because a sent request can't be edited, the sender needs to create a new one instead of extending it.
    * Already signed: that specific recipient has completed their signature; it's tied to their own unique link, so it won't happen if a different signer opens their own link.
    * Invalid: a broken or mistyped link, or one for a cancelled request, produces its own distinct error rather than "already signed."
  </Accordion>

  <Accordion title="Can either of two signers sign, or can my own company auto-sign its side?">
    No to both. There's no built-in 'either-signer' mode; your application must decide who specifically signs before creating the request. There's also no unattended or automatic signing on your own company's behalf; every signer, including someone on your team, must open their link and complete the signing flow.

    **See:** [Signing patterns - Pattern: Parallel signing](/guides/signing-patterns#pattern-parallel-signing)
  </Accordion>

  <Accordion title="What happens if two signers share one email, or a signing link gets forwarded?">
    Nothing breaks. Each recipient's signing link is identified by their own recipient ID, not by email, so two signers can share the same email address without conflict, and forwarding a link doesn't let someone else become a different signer. If a link reaches the wrong person, `identity_editable_fields` lets the actual signer correct their own identity before signing, and that correction is recorded in the audit trail.

    **See:** [Signing patterns - Pattern: Dynamic second signer](/guides/signing-patterns#pattern-dynamic-second-signer)
  </Accordion>

  <Accordion title="How do I enable QR-code signing on a phone?">
    Turn on **QR Code on Signing Page** in Workspace Settings to enable QR-code signing on a phone.

    This sets `show_qr_code` to `true`. Add the `{{signing_qr_code}}` placeholder to your email templates so the QR code appears.

    **See:** [Workspace settings - QR code in emails](/guides/workspace-settings#qr-code-in-emails-signingqrcode)
  </Accordion>
</AccordionGroup>

## Identity verification (OTP)

<AccordionGroup>
  <Accordion title="How long is an OTP code valid, and why am I not asked for it again when I reopen the signing link?">
    An OTP code is valid for 10 minutes, with up to 3 attempts before you need to request a new one.

    Resending is rate-limited to once every 60 seconds, and these values are fixed: they aren't configurable per workspace or request.

    Once you verify a code, Firma.dev stores a session token in your browser and issues a fresh 4-hour signing session on each subsequent visit, so reopening the same signing link in the same browser within that window skips the OTP prompt. That rolling session is capped at 12 hours from your last successful verification, after which you'll be asked to verify again regardless of activity.
  </Accordion>

  <Accordion title="Can I set a signing request's email/OTP language, or customize the OTP email?">
    You can set the OTP email's language per request, but not its wording. Set `language` on the signing request itself to override the workspace and company defaults for that request's signer-facing emails, including the OTP email. Custom email templates can't change the OTP email's wording, but you can skip OTP entirely per request by setting `settings.require_otp_verification` to `false`.

    **See:** [Localization](/guides/localization#email-language-settings), [White-Labeling](/guides/white-labeling#custom-email-sender-address)
  </Accordion>

  <Accordion title="Does Firma.dev support SMS OTP or national eID (BankID, MitID, FranceConnect)?">
    No. Firma.dev currently supports only email-based OTP for signer identity verification; there's no SMS OTP or national eID (BankID, MitID, FranceConnect, or similar) integration. Email OTP is included at no extra cost in Firma.dev's flat per-envelope pricing. This isn't stated anywhere as a near-term roadmap item, so treat it as not currently supported rather than something planned.
  </Accordion>
</AccordionGroup>

## Webhooks

<AccordionGroup>
  <Accordion title="Webhooks show enabled with zero failures, but nothing is delivered. Why?">
    This usually means the account-level webhook switch is off, even though the workspace shows enabled with zero failures.

    Turn it on under **Settings > Webhooks**, or through the API:

    * `PATCH /workspaces/{id}`: set `webhook_enabled` to `true` in the body to enable webhooks without the dashboard.
    * `ignore_company_webhooks`: make sure this isn't `true` on the workspace; it silently opts the workspace out of company webhooks.

    The dashboard test button bypasses the master switch, which is why tests succeed while real events are skipped with zero failures.

    **See:** [Webhooks](/guides/webhooks#two-levels-of-enablement)
  </Accordion>

  <Accordion title="How do company- vs. workspace-level webhooks differ for secrets, opt-out, and the viewed event?">
    Company- and workspace-level webhooks differ in their signing secrets, opt-out behavior, and how the viewed event fires.

    * Secrets: company- and workspace-level webhooks each have their own signing secret.
    * `ignore_company_webhooks`: lets a workspace opt out of its company's webhooks entirely, without affecting other workspaces.
    * `signing_request.viewed`: fires only on a recipient's first view, not on every subsequent open.

    **See:** [Webhooks](/guides/webhooks#handling-secret-rotation), [Webhooks](/guides/webhooks#two-levels-of-enablement), [Webhooks](/guides/webhooks#event-types)
  </Accordion>

  <Accordion title="Why do webhook deliveries fail with a redirect error?">
    Firma.dev does not follow HTTP redirects when delivering webhooks; this is deliberate SSRF protection, so a redirecting endpoint fails delivery outright. Register the exact URL your server serves; a mismatch in scheme, a `www` subdomain, the path, or a missing or extra trailing slash fails every delivery attempt.

    **See:** [Webhooks](/guides/webhooks#troubleshooting)
  </Accordion>

  <Accordion title="What's the webhook retry policy, timeout, and auto-disable threshold? Can I resend past events?">
    Your endpoint must answer with a 2xx within 5 seconds; failed deliveries are retried automatically, and the endpoint is disabled after 50 consecutive failures. You can retry a single event from the dashboard event log, but there is no bulk resend, and events from before the webhook existed are never backfilled.

    **See:** [Webhooks](/guides/webhooks#retry-behavior)
  </Accordion>

  <Accordion title="Should I poll GET /signing-requests/{id} for status instead of using webhooks?">
    No, use webhooks instead of polling for status changes.

    * `GET /signing-requests/{id}`: don't poll this endpoint for status; webhooks push updates instead.

    **See:** [Rate Limits](/guides/rate-limits#best-practices-for-rate-limits), [Webhooks](/guides/webhooks)
  </Accordion>
</AccordionGroup>

## Email delivery & templates

<AccordionGroup>
  <Accordion title="What does the RECIPIENT_EMAIL_SUPPRESSED (422) error mean, and how do I get an address unblocked?">
    `RECIPIENT_EMAIL_SUPPRESSED` (HTTP 422) means the recipient is on Firma.dev's suppression list; contact support to get an address unblocked.

    **See:** [Email Deliverability](/guides/email-deliverability#the-recipientemailsuppressed-error), [Requesting removal](/guides/email-deliverability#requesting-removal)
  </Accordion>

  <Accordion title="Can I customize the sender name and email address on signing invitations?">
    The sender name comes from the workspace name, falling back to the company name. The address uses your verified sending domain; set its local part with `email_local_part` at the company or workspace level.

    **See:** [Custom email sender address](/guides/white-labeling#custom-email-sender-address)
  </Accordion>

  <Accordion title="How do I stop the completion email, skip the certificate, or handle CC attachments?">
    Control these through the signing request's `settings` object:

    ```json theme={null}
    {
      "send_finish_email": false,
      "attach_pdf_on_finish": false,
      "allow_download": false
    }
    ```

    * `send_finish_email: false`: stops the completion email.
    * `attach_pdf_on_finish: false`: sends a download link instead of attaching the PDF.
    * `document_only_download_url`: shares the document without the certificate, instead of `final_document_download_url`.
    * `certificate_only_download_url`: returns the certificate on its own.
    * `allow_download: false`: disables download links entirely, as a separate control from `attach_pdf_on_finish`.

    CC recipients receive the completed document as an email attachment under the same settings as the signer's copy.

    **See:** [Disabling Firma.dev emails](/guides/white-labeling#disabling-firma-emails)
  </Accordion>

  <Accordion title="What placeholders do email templates support, and can I customize them per language?">
    Custom templates use `{{placeholder}}` syntax.

    Legacy `[bracket]` syntax also works and is case-insensitive; an unresolved placeholder renders as nothing, not raw text.

    * `{{team_name}}`: an alias of `{{workspace_name}}`.
    * `{{team_email}}`: an alias of `{{workspace_email}}`.
    * `{{download_link}}`: resolves only in completion emails.

    No, templates don't vary by language: one template applies to every recipient, so per-language branded templates need a separate workspace each. There's no live preview or custom per-request variables.

    **See:** [Custom email templates](/guides/white-labeling#custom-email-templates)
  </Accordion>

  <Accordion title="Can I control the timezone or date format shown in emails?">
    Yes, through the API; the setting isn't exposed in the dashboard yet.

    * `timezone`: an IANA timezone set on the workspace through the settings API.
    * `default_timezone`: the company-level fallback when the workspace timezone isn't set.

    Placeholders such as `{{expiration_date}}` in signing emails use that timezone and the email's language. UTC remains the default when neither is set.

    **See:** [Supported timezones](/guides/workspace-settings#supported-timezones)
  </Accordion>

  <Accordion title="Why are signer emails in English when my workspace is set to another language?">
    Language resolves per signing request first, then workspace, then company.

    A company or workspace created through the API defaults to `en` unless you set `language` explicitly. Set it on the workspace, or pass `language` on the request, and new signer emails will use it.

    **See:** [Email language settings](/guides/localization#email-language-settings)
  </Accordion>
</AccordionGroup>

## Custom sending domains

<AccordionGroup>
  <Accordion title="Which DNS records do I need, and what's the domain verify flow?">
    Setting up a custom sending domain requires a few DNS records added in two stages: one to verify ownership, then a few more to finalize. No MX record is needed at any step, since Firma.dev only sends mail through the domain and never receives it.

    **See:** [DNS records you'll need](/guides/custom-domains#dns-records-youll-need)
  </Accordion>

  <Accordion title="What does 'Domain conflict' or a stuck 'finalizing' status mean?">
    A 'Domain Conflict' status (or a stuck 'Configuring') means the domain is already registered under a different Resend account, often your own; the fix is a dedicated subdomain like `sign.yourcompany.com`, which verifies independently. Removing the domain from Firma.dev releases Firma.dev's own registration for reuse elsewhere, but has no effect on a registration in someone else's Resend account.

    **See:** [Already using Resend for your own email?](/guides/custom-domains#already-using-resend-for-your-own-email)
  </Accordion>

  <Accordion title="Why does domain status stay pending or unverified when DNS is correct?">
    Call `verify-dns` again; it checks live every time, so a transient hiccup can report the domain as unverified even when the DNS is correct.

    **See:** [Verification states](/guides/custom-domains#verification-states), [Known display quirk](/guides/custom-domains#known-display-quirk-pending-after-a-domain-is-already-verified)
  </Accordion>

  <Accordion title="Why did my verified domain stop working and emails fall back to Firma.dev's address?">
    A verified domain moves to 'Failed' when its DNS records stop checking out. Firma.dev only marks it invalid after two consecutive failed background checks, not the first blip, to avoid flapping on a transient hiccup. While a domain is failed or not yet verified, Firma.dev automatically sends from its own default domain instead of yours.

    **See:** [Verified domain later shows Failed](/guides/custom-domains#verification-states)
  </Accordion>

  <Accordion title="Can I use the same sending domain in more than one workspace?">
    Yes, add and verify the domain separately in each workspace where you want to use it.

    **See:** [Custom Domains](/guides/custom-domains), [Custom email domains](/guides/white-labeling#custom-email-domains)
  </Accordion>
</AccordionGroup>

## Legal validity / certificates / security

<AccordionGroup>
  <Accordion title="What signature level does Firma.dev provide, and is it legally valid under eIDAS/ESIGN?">
    Firma.dev provides an Advanced Electronic Signature (AES) under eIDAS Art. 3(11)/26, meeting the eIDAS admissibility floor and ESIGN Act/UETA requirements for most contracts; Firma.dev is not a Qualified Trust Service Provider and doesn't issue Qualified Electronic Signatures. The seal itself is `PAdES-B-LTA` (Baseline Long-Term Archival), issued from Firma.dev's own certificate authority, with an embedded RFC 3161 timestamp.

    **See:** [Legal Validity & eIDAS Compliance](/guides/legal-validity#what-firma-provides)
  </Accordion>

  <Accordion title="Why does Adobe Acrobat or the EU DSS validator show my signature as untrusted?">
    Firma.dev's digital seal is issued by Firma.dev's own certificate authority, not one chaining to Adobe's Approved Trust List (AATL) or the EU Trusted List (EUTL), so Acrobat and similar viewers won't show the automatic green checkmark; the seal itself is still fully valid. Verify it in your PDF viewer's signature panel, or independently at [app.firma.dev/validate-signature](https://app.firma.dev/validate-signature).

    **See:** [Why there's no green checkmark in Adobe Acrobat](/guides/legal-validity#why-theres-no-green-checkmark-in-adobe-acrobat)
  </Accordion>

  <Accordion title="Where is my data stored, and is Firma.dev SOC 2 / ISO certified?">
    Your data stays entirely within the EU, and Firma.dev is not SOC 2 or ISO 27001 certified, though its practices align with both frameworks.

    **See:** [Security & Compliance](/guides/security#data-residency)
  </Accordion>

  <Accordion title="How do I delete signing requests or documents, for example for a GDPR request?">
    You can delete an unsent (draft) signing request at any time, from the dashboard or via the API:

    ```text theme={null}
    DELETE /signing-requests/{id}
    ```

    Once a request has been sent it can no longer be deleted, only cancelled. A completed, signed document is a legal record: the data a signer captured is never modified after signing, and there is no self-serve endpoint for removing a single signer's data from it. If you need a completed signing request removed to satisfy a data-protection request, contact [support@firma.dev](mailto:support@firma.dev).
  </Accordion>

  <Accordion title="In which language is the completion certificate generated, and can it show my logo?">
    The completion certificate is generated in your workspace's configured language, not the individual signer's language or a signing-request-level override, and yes, it can show your logo. It uses a fallback chain: workspace logo, then company logo, then Firma.dev's default logo, and it prints the workspace's own name. Certificate timestamps use the workspace's configured timezone, falling back to UTC if none is set.
  </Accordion>

  <Accordion title="Are archive timestamps renewed over time, and what happens if a signature is challenged?">
    No. Firma.dev applies its `PAdES-B-LTA` seal once, at signing time, and never re-stamps or renews it afterward; for very long retention windows, apply your own re-timestamping when you archive the file. If a signature is challenged, signer-identity, consent, and record-keeping responsibilities are set out in Firma.dev's Terms of Service.

    **See:** [Legal Validity: What Firma.dev provides](/guides/legal-validity#what-firma-provides), [Audit Trail](/guides/audit-trail)
  </Accordion>

  <Accordion title="Can I remove the Signing Request ID header from the signed PDF?">
    No, you can't remove the Signing Request ID header from the signed PDF.

    `Signing Request ID: <id>` is drawn on every page of the signed PDF and completion certificate, in small gray text near the top margin; there is no workspace or API setting to turn it off.

    The header is drawn with an embedded font, so sealed documents pass PDF/A-2b validation.
  </Accordion>

  <Accordion title="Is Firma.dev suitable for use in France: eIDAS, GDPR and HDS?">
    Firma.dev is suitable for most French use cases under eIDAS and GDPR, but not for HDS-regulated health data: Firma.dev does not hold an HDS (French health-data hosting) certification. Signatures are sealed as `PAdES-B-LTA`. For GDPR, Firma.dev acts as the data processor; a Data Processing Agreement is available on request from [support@firma.dev](mailto:support@firma.dev).

    **See:** [Security](/guides/security), [Legal Validity & eIDAS Compliance](/guides/legal-validity)
  </Accordion>
</AccordionGroup>

## Workspaces & multi-tenant

<AccordionGroup>
  <Accordion title="Should each customer get their own workspace? Is there a limit?">
    Yes, giving each end customer their own workspace is Firma.dev's recommended default for multi-tenant platforms; data in one workspace is never visible from another. There's no limit on how many workspaces you can create under one company, and no extra cost per workspace.

    **See:** [Multi-Tenant Architecture](/guides/multi-tenant#architecture-overview-company-workspaces), [Workspaces](/guides/creating-workspaces)
  </Accordion>

  <Accordion title="What is the protected/default workspace, and why do I get a 403 PROTECTED_WORKSPACE error?">
    Every company gets exactly one default workspace, created automatically at signup and flagged `protected`.

    It's meant to be managed from the dashboard rather than the API; calling a management endpoint against it with a regular API key returns a `403` with code `PROTECTED_WORKSPACE`.

    For account-wide settings, use:

    ```text theme={null}
    PUT /company/settings
    ```

    This endpoint accepts `default_timezone` and `language`, among other fields. For anything you need to manage directly via the API, create separate, non-protected workspaces instead.

    **See:** [Workspaces: Edge cases & troubleshooting](/guides/creating-workspaces#edge-cases-troubleshooting), [Workspace Settings: Update workspace settings](/guides/workspace-settings#update-workspace-settings)
  </Accordion>
</AccordionGroup>

## White-labeling & embedding

<AccordionGroup>
  <Accordion title="What parts of Firma.dev can I white-label, and can I use my own API domain?">
    You can white-label signing-request emails, signer terms-acceptance text, and the signing page and embeds, but `api.firma.dev` itself can't be proxied under your own domain, only the email-sending domain is customizable. The completion certificate can also be white-labeled, with your logo replacing Firma.dev's. `show_custom_branding_only` only strips Firma.dev's support contact line from emails; it doesn't remove Firma.dev's presence from the signing page itself.
  </Accordion>

  <Accordion title="How do I set brand colors and a logo per workspace via the API?">
    Set workspace colors and a logo with these two endpoints:

    ```text theme={null}
    PUT /workspace/{workspace_id}/settings
    POST /workspaces/{workspace_id}/logo
    ```

    These settings apply across the signing page, embeds, and signing emails.

    **See:** [White Labeling](/guides/white-labeling#color-theming)
  </Accordion>

  <Accordion title="Why does the embedded template editor clip zoom/panning, and what about PDFs failing to load after a while?">
    Set `initialZoom` to control the embedded template editor's initial zoom directly.

    `autoFit` (boolean) is the alternative; `initialZoom` (number) takes precedence when both are set. Every document canvas supports panning via middle-mouse-button drag, leaving left-click free for field interaction.

    Signed document URLs expire after 1 hour. The embedded template editor auto-requests a fresh URL and retries up to 3 times instead of failing.

    If downloads are blocked, check for a `sandbox` attribute on your own page; Firma.dev's embed examples don't set one.

    **See:** [Embeddable template editor](/guides/embeddable-template-editor#configuration-options)
  </Accordion>

  <Accordion title="Can I inject custom CSS into embeds or embed just the signature box?">
    Neither is currently supported. Firma.dev's embeds (the template editor, signing-request editor, and the signing page) don't accept custom CSS, and there's no option to render only a signature field instead of the full document. If this is blocking your integration, share the use case with Firma.dev support.
  </Accordion>
</AccordionGroup>

## Tools / SDKs / limits

<AccordionGroup>
  <Accordion title="How do I connect Firma.dev's MCP servers, and which one should I use?">
    Firma.dev provides two MCP servers, the Data MCP for account access and the Docs MCP for documentation lookup; most developers connect both.

    **See:** [MCP Integration](/guides/mcp#setup)
  </Accordion>

  <Accordion title="Which SDKs does Firma.dev offer? Is there a Python SDK?">
    Firma.dev offers one official SDK, the TypeScript client `@firma-dev/sdk`, generated from the same OpenAPI spec as the API reference:

    ```bash theme={null}
    npm install @firma-dev/sdk
    ```

    There's no official Python SDK and no published roadmap commitment for one; call the REST API directly, for example with the `requests` library.

    **See:** [TypeScript SDK for the Firma.dev API](/guides/typescript-sdk#installation)
  </Accordion>

  <Accordion title="What are the API rate limits?">
    Rate limits are enforced per API key and vary depending on which operation you're calling.

    **See:** [Rate Limits](/guides/rate-limits#rate-limit-tiers)
  </Accordion>

  <Accordion title="Why do I see 'FunctionsFetchError: Failed to send a request to the Edge Function' in the console?">
    This client-side error means your browser's request to an edge function never reached the server:

    ```text theme={null}
    FunctionsFetchError: Failed to send a request to the Edge Function
    ```

    It comes from Supabase's JS SDK, for example due to an ad blocker, DNS filter, offline connection, or CORS block; it's a different error class than a genuine error response from the function itself.

    On Firma.dev's signing page, this most commonly comes from a background analytics call, which fails silently and doesn't affect your ability to view or sign the document.

    If it's happening on a call that's actually blocking your integration rather than analytics, check your network conditions before treating it as a Firma.dev-side error.
  </Accordion>
</AccordionGroup>

## For signers (received a document)

<AccordionGroup>
  <Accordion title="Where can I get a copy of a document after I sign it?">
    By default, everyone on the signing request, including CC'd recipients, is emailed a copy of the completed document once every signer has finished, not immediately after you personally sign. The email attaches the PDF automatically when it's under 8MB; larger files come as a download link instead. There's no signer login or dashboard to retrieve past documents yourself, so if you need a copy before everyone else has finished, ask the person who sent it to you (named in your invitation email).
  </Accordion>

  <Accordion title="I have a question about a document, want to undo my signature, or my link expired. What do I do?">
    Contact the sender named in your invitation email. Firma.dev is the e-signature platform they used to send the document, not a party to the agreement, so Firma.dev can't answer questions about its terms, resend an expired link, or act on the sender's behalf. If you haven't finished signing yet, you can decline the request instead; once you've signed, that signature is part of the permanent legal record and can't be undone by anyone, including Firma.dev support. Signing is always free for you: only the sender's account is billed.
  </Accordion>
</AccordionGroup>
