Skip to content

omnisign/docuseal

Omnisign DocuSeal: documents signed on a DocuSeal instance of one's own (open source, AGPL) or DocuSeal's cloud - a submission from a template, or from a PDF where the edition allows it, its submitters, embedded signing, reminders, the signed documents and the audit log, webhooks with their X-Docuseal-Signature checked; nothing leaves for a third party when self-hosted.

Floor
Provider · Omnisign
Version
1.x
Conformance suite
not wired
Verified for real
Verified for real
Licence
MIT
composer require omnisign/docuseal:1.x-dev

DocuSeal for omnisense/omnisign: an instance of one's own - open source, nothing leaves for a third party - or DocuSeal's cloud (https://api.docuseal.com, https://api.docuseal.eu). Simple signatures, by e-mail or in the application's page, from a template of the instance's or from the envelope's PDFs. Every call carries the API key as X-Auth-Token; JSON both ways.

Installation

composer require omnisign/docuseal

PHP 8.2 or later, omnisense/omnisign and symfony/http-client. A DocuSeal instance and its API key (Settings > API) - or DocuSeal's cloud.

docker run -d -p 3000:3000 -v docuseal:/data docuseal/docuseal       # an instance of one's own

The sources

Read on 2026-10-08: DocuSeal's API reference and its OpenAPI (console.docuseal.com/openapi.yml), and the open-source code itself (docusealco/docuseal: config/routes.rb, app/controllers/api/*, lib/submissions/serialize_for_api.rb, lib/webhook_urls/signatures.rb) - which says what the open-source edition has: no /submissions/pdf, a signature on webhooks.

Credentials

  • The instance's (or the cloud account's) API key: Settings, API.
  • For webhooks, a webhook created in the instance's settings, and its secret (whsec_...).

Options

Option Default
url required the API's root: https://<host>/api for an instance, https://api.docuseal.com or https://api.docuseal.eu for the cloud
api_key required sent as X-Auth-Token
app_url the url without /api (the cloud: https://docuseal.com) where signers' forms open: <app_url>/s/<slug>
webhook_secret, webhook_tolerance none, 300 the webhook's secret (whsec_...); without it, notify() is not supported
third_party told from the url whether the instance is someone else's: the cloud is

Templates and PDFs

Envelope::$template set POST /submissions: template_id, the submitters by role (Signer::$role; the first may leave it, "First Party"), external_id their key - the open-source edition's way
documents and fields POST /submissions/pdf: each document in base64, its fields (name, type, role: the signer's key, areas: x, y, w, h, page) - DocuSeal Pro and the cloud; an open-source instance answers 404, "This feature is available in Pro Edition"

DocuSeal sends at creation (e-mails, or nothing when embedded): create() answers SENT, send() reads the submission back.

fetch() GET /submissions/{id}: pending SENT, completed COMPLETED, declined, expired; archived: CANCELED. Submitters: awaiting WAITING, sent NOTIFIED, opened OPENED, completed SIGNED, declined DECLINED
remind() PUT /submitters/{id}, send_email: true, for each who has not signed
cancel() DELETE /submissions/{id}: archived
download() the completed submission's documents and its audit_log_url, fetched - the key sent only to the instance's own host
signingUrl() embed_src, or <app_url>/s/<slug>: a page of its own, or the docuseal-form web component's src
notify() X-Docuseal-Signature: <timestamp>.<hex HMAC-SHA-256 of "<timestamp>.<body>" under the secret>, five minutes' tolerance - as lib/webhook_urls/signatures.rb signs it; form.completed SIGNED, submission.completed COMPLETED...

Simple signatures only.

Capabilities

Request Supported
Create yes: from a template (POST /submissions), or from PDFs (POST /submissions/pdf: DocuSeal Pro and the cloud; an open-source instance refuses it)
Send reads the submission back: DocuSeal sends at creation
Fetch, Remind, Cancel, Download, SigningUrl yes
Notify with webhook_secret

capabilities(): simple; in the page; ordered; no identity check; third party only for the cloud (or third_party); documents; templates. Signer::$locale is not sent; SigningUrl's returnUrl is not read (the envelope's redirectUrl is DocuSeal's completed_redirect_url); a field's anchor is not read: fields are placed by page and position (w 200 and h 60 when not given). The signed documents' URLs are fetched with the API key only when they are on the API's own host.

Example

The installation script of the manual is this gateway's, run on 2026-10-08 against an open-source instance in Docker. On the recorded answers, on 2026-10-26, with a webhook signed as DocuSeal signs it:

docuseal
  > POST http://localhost:13300/api/submissions
  4 sent tenant=4 waiting http://localhost:13300/s/KKjaQ1uucspGL5
  notify: signed form.completed 4 tenant form.completed@7@2026-10-26T09:00:00Z

In Symfony:

omnisign:
    gateways:
        contracts:
            factory: docuseal
            options:
                url: '%env(DOCUSEAL_URL)%'
                api_key: '%env(DOCUSEAL_API_KEY)%'
                webhook_secret: '%env(default::DOCUSEAL_WEBHOOK_SECRET)%'

Errors

Answer Exception
401, 403 InvalidKeyException (The API key was refused (HTTP 401): ...)
other 4xx (an open-source instance's 404 on /submissions/pdf) ProviderException (<METHOD> <path>: HTTP <status>, <error>)
5xx, 429, no answer, a timeout (10 s) UnreachableException
a download of a submission not completed ProviderException
a level other than simple; no signer; neither template nor documents; a template signer without a role (but the first) InvalidConfigException, before any call
a signing URL for a signer not created with the envelope InvalidConfigException
a webhook that does not hold InvalidNotificationException

Verified, and not

The whole way on an open-source instance done on 2026-10-08: docuseal/docuseal run in Docker, set up, a one-page PDF uploaded as a template and given a signature field through the API; then create() from the template (embedded), signingUrl() (/s/<slug>), fetch() (SENT, the tenant WAITING), the tenant completed through the API, fetch() (COMPLETED, signed at...), download() (the signed PDF, 17,829 bytes, and the audit log, 54,542 bytes), a second submission cancel()ed and read back CANCELED. Tests/Fixtures holds the answers recorded that day
/submissions/pdf seen refused by the open-source edition (404, "available in Pro Edition"); its body follows DocuSeal's OpenAPI, not verified on Pro or the cloud
remind() accepted by the instance (200); the e-mail not observed - no mail server configured
Webhooks the signature by the tests, as DocuSeal's code computes it; no callback received from the instance
A signer signing in a browser not done: completed through the API

The package's tests (Tests/DocusealGatewayTest.php, 6 tests) pass on 2026-10-26 (PHP 8.4).

Responsibility

This package is an independent, unofficial client: it is not affiliated with, endorsed by or sponsored by DocuSeal. Whoever runs it against DocuSeal's cloud complies with docuseal.com/terms; see the README's Responsibility section.

Propose a change docs/index.md