signedly / sdk
Signedly REST API client for PHP: send documents for e-signature, track them and verify webhooks
Requires
- php: ^7.4 || ^8.0
- ext-curl: *
- ext-json: *
- ext-mbstring: *
- guzzlehttp/guzzle: ^7.3
- guzzlehttp/psr7: ^1.7 || ^2.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-03 17:23:43 UTC
README
Client libraries for the Signedly REST API (/ap1/) in Python, Node/TypeScript,
PHP and Java. Each is generated from the API's OpenAPI spec
(openapi/signedly-ap1.json) with openapi-generator
7.10.0, plus a few hand-written helpers:
- Log in and stay logged in: give the client ID and secret, and the access token is fetched on the first call and renewed (refresh token, then the keys again) before it expires.
- Check webhook signatures:
Signedly-Signatureagainst the endpoint's secret, refused when older than 5 minutes. - Sandbox: test keys work exactly like live ones; what they make is a watermarked, unbilled test document.
The API itself (every endpoint, field and status) is documented at
https://l0ads.signedly.com/swaggerap1/. Each SDK's own README lists its classes
and methods.
| Folder | Package | Generator |
|---|---|---|
python/ |
signedly (PyPI) |
python |
node/ |
@signedly/sdk (npm) |
typescript-axios |
php/ |
signedly/sdk (Packagist, from the root composer.json) |
php |
java/ |
com.signedly:signedly-sdk (Maven Central) |
java, native library (Java 11+) |
Install
| Language | Install |
|---|---|
| Python 3.8+ | pip install signedly |
| Node / TypeScript | npm install @signedly/sdk |
| PHP 7.4+ | composer require signedly/sdk |
| Java 11+ | Maven com.signedly:signedly-sdk (Gradle: implementation "com.signedly:signedly-sdk:0.1.1") |
Java with Maven:
<dependency> <groupId>com.signedly</groupId> <artifactId>signedly-sdk</artifactId> <version>0.1.1</version> </dependency>
Quick start
Generate a client ID and secret in Signedly under Account & Settings → API (test keys for the sandbox, live keys for real documents).
Python
from signedly.helpers import SignedlyClient from signedly.api.documents_api import DocumentsApi client = SignedlyClient(CLIENT_ID, CLIENT_SECRET) for document in DocumentsApi(client.api_client).list_documents().results: print(document.id, document.status)
Node / TypeScript
import { DocumentsApi } from "@signedly/sdk"; import { signedlyConfiguration } from "@signedly/sdk/dist/helpers"; const config = signedlyConfiguration(CLIENT_ID, CLIENT_SECRET); const { data } = await new DocumentsApi(config).listDocuments();
PHP
$auth = new \Signedly\Helpers\SignedlyAuth($clientId, $clientSecret); $documents = (new \Signedly\Api\DocumentsApi(null, $auth->config()))->listDocuments();
Call $auth->config() again in long-running jobs, so the token is renewed.
Java
ApiClient client = SignedlyAuth.client(clientId, clientSecret); DocumentPage page = new DocumentsApi(client).listDocuments(null, null, null, null, null);
The usual flow is: upload, add signatories, place fields, send, then follow the
document by webhook or by polling. See "Sending a document for signing" in the
API docs. Every SDK has a method per endpoint, named after its operation, e.g.
upload_document, create_signatory, create_document_fields, send_document,
get_download_link, create_bulk_send, create_webhook_endpoint.
Webhooks
Check every event before trusting it. Pass the raw request body:
| Language | Call |
|---|---|
| Python | signedly.helpers.verify_webhook_signature(secret, header, raw_body) |
| Node | verifyWebhookSignature(secret, header, rawBody) from @signedly/sdk/dist/helpers |
| PHP | \Signedly\Helpers\Webhook::verifySignature($secret, $header, $rawBody) |
| Java | com.signedly.helpers.Webhook.verifySignature(secret, header, rawBody) |
Sandbox
Generate test keys in Account & Settings → API and pass them instead of the live
ones. Documents made with them carry "TEST – NOT LEGALLY BINDING" on every page,
their emails start with [TEST], they aren't billed, and an organisation can make
50 a month.
Changing the SDKs
- Generated code is never edited by hand. Change the API (its docs live in
the backend repo,
backend/api/schema/), then:scripts/update-spec.sh # production's spec, then regenerate scripts/update-spec.sh http://localhost:8000 # or a local backend's scripts/generate.sh # regenerate from the committed spec only
The script downloads the pinned generator (checksum checked) into.cache/. It needs Java 11+. - Hand-written files are listed in each SDK's
.openapi-generator-ignore, so regenerating keeps them:python/signedly/helpers.pynode/helpers.tsphp/lib/Helpers/java/src/main/java/com/signedly/helpers/- their tests.
- Generator settings are in
config/<language>.yaml(package names, versions, author, links and license). - Template overrides are in
config/templates/<language>/: every SDK'sREADME.md(install from the registry, log in with the helper), Node'spackage.json(author, description,files), Java'spom.xml(the Maven Central publishing plugin) and Java'sapi.mustache(multipart uploads skip optional fields left null, give the file's type from its name, and are sent with their length, not chunked). They are copies of openapi-generator 7.10.0's own templates, so re-copy them when the generator version changes. - Author and license:
scripts/generate.shadds Signedly's contact (support@signedly.com) and the MIT license to a copy of the spec, so the committed spec stays exactly what production serves. - PHP on Packagist: Packagist reads the root
composer.json, which loadsphp/lib/. Itsrequiremust matchphp/composer.json(CI checks), and.gitattributesleaves the other languages out of PHP installs.
CI (.github/workflows/):
sdks.yml, on every PR:- regenerating must change nothing (drift);
- each SDK builds, and its helper tests run;
- each SDK logs in through its helper against a fake Signedly and must send the
token (
scripts/fake_signedly.py; Java'sLoginTest).
spec-check.yml, weekly and by hand: fails when production serves a different spec than the committed one. That means a backend release changed the API, so update the spec and publish new versions.
Publishing
Publishing needs Signedly's registry accounts and is done by a person. Every
registry keeps a published version for good (PyPI and Maven Central never take the
same version again), so publish only from an up-to-date integration with CI green.
Each SDK has its own version (config/<language>.yaml): release only the ones
that changed. Packagist takes the PHP version from the git tag vX.Y.Z.
Accounts (once)
Use the username signedly on each, keep logins and recovery codes in the team
password manager, and add a second owner.
- PyPI (https://pypi.org): turn on two-factor authentication. For the first
upload make an API token scoped to the entire account; afterwards replace it with
one scoped to the
signedlyproject. - npm (https://www.npmjs.com): turn on two-factor authentication for
authorization and writes, and create the free organisation
signedly. - Packagist (https://packagist.org): sign in with GitHub as an admin of the
signedlyorg, Submithttps://github.com/signedly/signedly-sdks. If the package page says it isn't updated automatically, add a GitHub webhook tohttps://packagist.org/api/github?username=<packagist username>(JSON, push events, secret = the Packagist API token). - Maven Central (https://central.sonatype.com): sign up with email, add the
namespace
com.signedlyand verify it with the TXT record it shows (signedly.com's DNS is at GoDaddy). Generate a user token and put it in~/.m2/settings.xml:<settings><servers><server> <id>central</id><username>TOKEN_USERNAME</username><password>TOKEN_PASSWORD</password> </server></servers></settings>
Make a GPG key (gpg --full-generate-key, RSA 4096) and send its public half tokeyserver.ubuntu.comandkeys.openpgp.org(gpg --keyserver <server> --send-keys <KEYID>).
Each release
- Bump the version of each SDK that changed in its
config/<language>.yaml(for Java, also in the install lines of this README), runscripts/generate.sh, and merge that PR. - From
integration, for the SDKs you bumped:# PyPI cd python && python -m pip install --upgrade build twine && python -m build \ && twine check dist/* && TWINE_USERNAME=__token__ twine upload dist/* && cd .. # npm (builds first, then asks for the two-factor code) cd node && npm install && npm publish --access public && cd .. # Packagist reads the tag git tag vX.Y.Z && git push origin vX.Y.Z # Maven Central: give GPG the passphrase in the terminal first, or signing # times out waiting for a pop-up export GPG_TTY=$(tty) echo test | gpg --pinentry-mode loopback --clearsign > /dev/null cd java && mvn -P sign-artifacts -DskipTests deploy && cd ..
- Maven Central: in Deployments on central.sonatype.com, wait for "Validated" and click Publish.
- Check each in a clean place:
pip install signedly,npm view @signedly/sdk,composer require signedly/sdk, and the artifact page https://central.sonatype.com/artifact/com.signedly/signedly-sdk.
License
MIT, see LICENSE.