PHP
API libraryThe official server library for PHP: create signature requests, track them and verify event notifications.
composer require wthaiq/wthaiq-php Server libraries (PHP · Node.js · Python) that create and track signature requests and verify event notifications, and two in-app signing libraries (iOS · Android) that show the signing page inside your app with no secret key in it. What you learn in one library applies to the rest.
All the libraries are available now on GitHub and the standard package registries at version v1.0.0.
Each box carries the install command, the runtime requirements and the package source, and the GitHub and Package buttons open the repository and the package source.
The official server library for PHP: create signature requests, track them and verify event notifications.
composer require wthaiq/wthaiq-php The official server library for Node.js, with complete TypeScript definitions and no runtime dependencies.
npm install wthaiqThe official server library for Python, with synchronous and asynchronous clients and no required dependencies.
pip install wthaiqSwiftUI and UIKit APIs that show the signing page inside your app and report the session result, with no secret key in the app.
.package(url: "https://github.com/wthaiq/wthaiq-ios", from: "1.0.0") Jetpack Compose, Fragment and Activity Result APIs that show the signing page inside your app, with no secret key in the app.
implementation("com.wthaiq:signing:1.0.0") Each library has its install command, a quick start example taken from its guide, what it covers and its runtime requirements.
The official server library for PHP: create signature requests, track them and verify event notifications.
composer require wthaiq/wthaiq-phprequire 'vendor/autoload.php';
$wthaiq = new \Wthaiq\Client(getenv('WTHAIQ_API_KEY'));
$request = $wthaiq->signatureRequests->create([
'source' => ['type' => 'template', 'template_id' => 'tpl_123'],
'signers' => [['name' => 'Noha Hassan', 'email' => 'noha@example.com']],
]);
echo $request->id . ' ' . $request->status; // sr_3n8Kd2Qa1V... sentWhat sets it apart: Uses cURL by default and accepts any PSR-18 client (Guzzle · Symfony HttpClient), with immutable typed response objects and support for PHP 8.1 to 8.4.
The official server library for Node.js, with complete TypeScript definitions and no runtime dependencies.
npm install wthaiqimport Wthaiq from 'wthaiq';
const wt = new Wthaiq(process.env.WTHAIQ_API_KEY);
const sr = await wt.signatureRequests.create({
title: 'Employment contract',
source: { type: 'template', template_id: 'tpl_123' },
legal_level: 'aes',
signers: [{ name: 'Ahmed Ali', email: 'ahmed@example.com', method: 'draw', require_identity: true }],
});
console.log(sr.id, sr.status); // sr_3f1c… sentWhat sets it apart: Written in TypeScript with complete definitions, ships ESM and CommonJS, accepts an AbortSignal to cancel a call, and verifies notifications synchronously, including on edge runtimes.
The official server library for Python, with synchronous and asynchronous clients and no required dependencies.
pip install wthaiqimport os
import wthaiq
wt = wthaiq.Client(os.environ["WTHAIQ_API_KEY"]) # sk_test_... while you build
sr = wt.signature_requests.create(
title="عقد عمل — أحمد سامي",
source={"type": "template", "template_id": "tpl_123"},
legal_level="aes",
signers=[{"name": "أحمد سامي", "email": "ahmed@example.com", "method": "draw"}],
)
print(sr.id, sr.status) # sr_3n8Kd2Qa1V... sentWhat sets it apart: A synchronous Client and an asynchronous AsyncClient with the same methods, full typing (py.typed), and optional httpx for true asynchronous I/O.
SwiftUI and UIKit APIs that show the signing page inside your app and report the session result, with no secret key in the app.
.package(url: "https://github.com/wthaiq/wthaiq-ios", from: "1.0.0")import SwiftUI
import WthaiqSigning
struct OrderView: View {
@State private var signingURL: URL?
@State private var isSigning = false
var body: some View {
Button("Sign the contract") {
Task {
signingURL = try? await MyBackend.signingURL(forOrder: 42) // your API call
isSigning = signingURL != nil
}
}
.wthaiqSigning(isPresented: $isSigning, url: signingURL) { result in
if case .signed = result { /* confirm on your backend via webhooks */ }
}
}
}What sets it apart: The SwiftUI modifier .wthaiqSigning(isPresented:url:) or WthaiqSigningSheet; in UIKit, presentWthaiqSigning(url:) or WthaiqSigningViewController with a delegate; distributed through Swift Package Manager only.
Jetpack Compose, Fragment and Activity Result APIs that show the signing page inside your app, with no secret key in the app.
implementation("com.wthaiq:signing:1.0.0")class OrderActivity : ComponentActivity() {
private val signing = registerForActivityResult(WthaiqSigning.Contract()) { result ->
when (result) {
is SigningResult.Signed -> showConfirming(result.outcome.reference.signatureRequestId)
is SigningResult.Declined -> showDeclined(result.outcome.reason)
SigningResult.Canceled -> Unit
SigningResult.Expired -> requestNewLink()
is SigningResult.Failed -> showError(result.error)
}
}
private fun sign(signingUrl: String) {
signing.launch(signingUrl)
}
}What sets it apart: Activity Result API via WthaiqSigning.Contract() · Jetpack Compose via rememberWthaiqSigningLauncher or WthaiqSigningSheet with the additional com.wthaiq:signing-compose artifact · WthaiqSigningFragment inside your screen · Kotlin or Java · AndroidX dependencies only.
No need to rebuild networking and security logic: the server libraries (PHP · Node.js · Python) implement the following capabilities the same way, for a consistent experience across all your projects.
On connection errors, timeouts and transient responses (429 or 5xx), the library retries with exponential backoff that honours the Retry-After header, and automatically attaches an Idempotency-Key to every POST request and reuses it across its retries, so the same resource is never created twice.
Browse thousands of records without managing cursors yourself: the list method returns one page, and the iterator fetches the following pages automatically until the last item.
A ready-made helper verifies the Wthaiq-Signature header with a constant-time comparison, rejects timestamps older than 300 seconds, and returns the typed event once verified.
API errors become exceptions classified by type: authentication, invalid request, rate limit, conflict and connection; each carries the fields code · param · request_id for quick diagnosis.
Every library sends the header Wthaiq-Version: 2026-07-01 pinned on every request, so later changes do not affect your integrations. You can set a different version when you initialise the client.
Set the timeout per attempt and the number of retries per client or per call, cancel a call in Node.js with an AbortSignal, and use your own HTTP client in PHP (PSR-18) or Python (httpx).
Your server creates the signing link with its secret key and returns it to the app; the library only shows the page. It accepts only https links on Wthaiq domains and keeps session data in memory by default.
The library reports to your app once with one of five results: signed, declined, canceled, expired or failed. That result drives your interface; the proof is the event notification that reaches your server.
The library interface runs in Arabic right-to-left or in English, follows the system dark mode, and includes loading, error and retry screens, plus ID attachments, camera and identity verification inside the page.
We keep the library version separate from the API version and keep changes within predictable limits, so you can plan upgrades with confidence.
Every library follows semantic versioning MAJOR.MINOR.PATCH. Breaking changes are only introduced in a new MAJOR version; compatible additions and bug fixes ship safely in MINOR and PATCH releases.
The library version is independent of the API version pinned by the header Wthaiq-Version, so you can upgrade the library without changing API behavior.
Every library has a CHANGELOG file in its repository recording what was added and changed in each release, while API changes are dated by the version header and every released version stays supported.
Follow the Changelog to learn early what needs updating.
| The library | Minimum runtime requirements | Package source | Version |
|---|---|---|---|
| PHP | PHP 8.1 or later · curl / json extensions | Packagist · wthaiq/wthaiq-php | Available · v1.0.0 |
| Node.js | Node.js 18 or later · TypeScript definitions included · ESM / CommonJS | npm · wthaiq | Available · v1.0.0 |
| Python | Python 3.10 or later · no required dependencies | PyPI · wthaiq | Available · v1.0.0 |
| iOS | iOS 15 or later · Swift 5.9 or later | Swift Package · WthaiqSigning | Available · v1.0.0 |
| Android | Android 7.0 (minSdk 24) or later · Kotlin / Java | Maven Central · com.wthaiq:signing | Available · v1.0.0 |
Wthaiq-Version: 2026-07-01 by default, and connects tohttps://wthaiq.com/api/v1, and authenticate through Authorization: Bearer sk_.... A live key sk_ actually sends and is billed, while its test version sk_test_ deducts no balance and sends no message to anyone. The two in-app signing libraries carry no key at all.Five official libraries: server libraries (PHP · Node.js · Python) that call the full API, and two in-app signing libraries (iOS · Android) that show the signing page inside your app. The server libraries share the same resource interface and operation names, so what you learn in one language applies to the rest.
Yes, under the MIT licence on the github.com/wthaiq organization, distributed through the standard package registries: Packagist · npm · PyPI · Swift Package · Maven Central.
The library retries automatically (twice by default) on connection errors, timeouts and transient responses (429 or 5xx), with exponential backoff that honours the Retry-After header. It attaches an Idempotency-Key to every POST request and reuses it across its retries, so the same resource is never created twice, and you can pass your own key per call.
The server libraries send the Wthaiq-Version: 2026-07-01 header pinned on every request, so responses keep their shape despite later updates. You can choose another version when you initialise the client, or for a single call after testing it.
A signing link that your server creates with one of the server libraries or directly through the API; no key goes into the app. The library shows the page and reports the result to your app once, and the event notification that reaches your server is the final proof.
PHP: PHP 8.1 or later · curl / json extensions; Node.js: Node.js 18 or later · TypeScript definitions included · ESM / CommonJS; Python: Python 3.10 or later · no required dependencies; iOS: iOS 15 or later · Swift 5.9 or later; Android: Android 7.0 (minSdk 24) or later · Kotlin / Java. All the libraries follow semantic versioning (SemVer): compatible additions in minor releases, and any breaking change in a new major release.
Install your library and follow the quick start guide to create your first signature request in minutes.