Add Aadhaar eSign to WordPress
There is no SignYu plugin to install; a small custom plugin is enough. This guide sends a PDF from the media library for Aadhaar eSign with wp_remote_post, and registers a REST route that verifies SignYu webhooks with the raw request body. It suits WordPress sites that sell services or collect applications.
Updated 2026-10-01
What you need
- WordPress 6 or newer, with permission to add a plugin or a must-use plugin.
- HTTPS on the site, so webhooks can reach it.
- A SignYu API key (starts with sk_live_). API access costs ₹999/month with a 3-day free trial; create the key under Developers in the dashboard.
- Signature credits for your signers, from ₹15 per signature (₹15 per signature on packs of 10 or more). Sending uses one credit per signer.
- A webhook endpoint added under Developers, and its signing secret.
Step 1: Define the secrets in wp-config.php
Constants in wp-config.php stay out of the database and out of exported content.
define( 'SIGNYU_API_KEY', 'sk_live_your_api_key' );
define( 'SIGNYU_WEBHOOK_SECRET', 'your_endpoint_secret' );Step 2: Upload a PDF with wp_remote_post
The WordPress HTTP API does not build multipart bodies for files, so the function below assembles one. It reads a PDF from the media library by attachment ID.
<?php
/**
* Plugin Name: SignYu eSign
*/
const SIGNYU_BASE = 'https://signyu.com/api/v1';
function signyu_request( $method, $path, $args = array() ) {
$args = array_merge_recursive( array(
'method' => $method,
'timeout' => 60,
'headers' => array( 'Authorization' => 'Bearer ' . SIGNYU_API_KEY ),
), $args );
$res = wp_remote_request( SIGNYU_BASE . $path, $args );
if ( is_wp_error( $res ) ) {
return $res;
}
$code = wp_remote_retrieve_response_code( $res );
$body = json_decode( wp_remote_retrieve_body( $res ), true );
if ( $code >= 300 ) {
return new WP_Error( $body['error'] ?? 'signyu_error', $body['message'] ?? 'SignYu error', array( 'status' => $code ) );
}
return $body;
}
function signyu_create_document( $attachment_id, $name ) {
$path = get_attached_file( $attachment_id );
$boundary = wp_generate_password( 24, false );
$body = "--$boundary\r\n"
. "Content-Disposition: form-data; name=\"name\"\r\n\r\n$name\r\n"
. "--$boundary\r\n"
. 'Content-Disposition: form-data; name="file"; filename="' . basename( $path ) . "\"\r\n"
. "Content-Type: application/pdf\r\n\r\n"
. file_get_contents( $path ) . "\r\n"
. "--$boundary--\r\n";
return signyu_request( 'POST', '/documents', array(
'headers' => array( 'Content-Type' => "multipart/form-data; boundary=$boundary" ),
'body' => $body,
) );
}Step 3: Add signers, send and save the link
Store the documentId and signing link as post meta on whatever represents the deal: an order, an application or a custom post type.
function signyu_send_for_signature( $post_id, $attachment_id, $signer ) {
$doc = signyu_create_document( $attachment_id, get_the_title( $post_id ) );
if ( is_wp_error( $doc ) ) {
return $doc;
}
$added = signyu_request( 'POST', "/documents/{$doc['documentId']}/signers", array(
'headers' => array( 'Content-Type' => 'application/json' ),
'body' => wp_json_encode( array( 'signers' => array( $signer ) ) ),
) );
if ( is_wp_error( $added ) ) {
return $added;
}
$sent = signyu_request( 'POST', "/documents/{$doc['documentId']}/send" );
if ( is_wp_error( $sent ) ) {
// 'insufficient_credits' (402) means nothing was sent; show it to the admin.
return $sent;
}
update_post_meta( $post_id, '_signyu_document_id', $doc['documentId'] );
update_post_meta( $post_id, '_signyu_status', 'SENT' );
update_post_meta( $post_id, '_signyu_sign_url', $sent['signers'][0]['signUrl'] );
return $sent;
}Verify webhooks
A REST route receives the webhook at /wp-json/signyu/v1/webhook. $request->get_body() returns the raw body; hash_hmac and hash_equals verify it. permission_callback is __return_true because the HMAC is the authentication.
add_action( 'rest_api_init', function () {
register_rest_route( 'signyu/v1', '/webhook', array(
'methods' => 'POST',
'permission_callback' => '__return_true',
'callback' => 'signyu_handle_webhook',
) );
} );
function signyu_handle_webhook( WP_REST_Request $request ) {
$raw = $request->get_body();
$expected = 'sha256=' . hash_hmac( 'sha256', $raw, SIGNYU_WEBHOOK_SECRET );
$received = (string) $request->get_header( 'X-SignSetu-Signature' );
if ( ! hash_equals( $expected, $received ) ) {
return new WP_REST_Response( array( 'error' => 'invalid signature' ), 400 );
}
$event = json_decode( $raw, true );
$posts = get_posts( array(
'post_type' => 'any',
'meta_key' => '_signyu_document_id',
'meta_value' => $event['documentId'],
'fields' => 'ids',
'numberposts' => 1,
) );
if ( $posts ) {
update_post_meta( $posts[0], '_signyu_status', $event['status'] );
if ( 'document.completed' === $event['event'] ) {
wp_schedule_single_event( time(), 'signyu_archive_signed_pdf', array( $posts[0], $event['documentId'] ) );
}
}
return new WP_REST_Response( null, 204 );
}Common mistakes
- Security plugins and some hosts block or rate limit /wp-json/ for anonymous requests. Allow the signyu/v1/webhook route.
- Saving signed PDFs into wp-content/uploads makes them publicly downloadable by URL. Store them outside the web root or behind an access check.
- WP-Cron only runs when someone visits the site; on low-traffic sites, set up a real cron job so the archive task runs promptly.
- Do not reuse signyu_request() for the downloadUrl, since it adds your Bearer key; use wp_remote_get on it directly.
- Webhooks are retried when your endpoint fails or times out after 10 seconds, so the same event can arrive more than once. Key your processing on documentId plus event plus signerId and ignore repeats.
Frequently asked questions
Can I trigger eSign from a WooCommerce order or a form plugin?
Yes. Call signyu_send_for_signature from a hook such as woocommerce_order_status_processing or your form plugin's after-submission action, passing the order or entry ID as the post ID.
Will this work on shared hosting?
Usually. You need outbound HTTPS, a PHP memory limit large enough to hold the PDF in memory, and a public HTTPS URL for the webhook.
Can visitors sign without leaving my site?
The signing step runs on SignYu and the eMudhra gateway for the Aadhaar OTP. Link or redirect to the stored signUrl; there is no embeddable iframe.
Is there a ready-made SignYu WordPress plugin?
Not at the moment. The code in this guide is a complete minimal plugin you can extend.
API reference
Get your API key
Start a 3-day free trial of API access and send your first document today.