Skip to content
SignYu
TemplatesPricingAPIDocsAboutBlogContact
  1. Home
  2. API
  3. Integrations
  4. WordPress

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

  • Quickstart
  • Documents
  • Webhooks
  • Errors

Other integration guides

  • Add Aadhaar eSign to a Next.js App Router Project
  • Aadhaar eSign API in PHP with Laravel
  • Send Aadhaar eSign Requests from Google Sheets

Get your API key

Start a 3-day free trial of API access and send your first document today.

Start free trialSee API pricing and features
SignYu

Pay-per-use Aadhaar eSign for Indian businesses, landlords, and individuals. Sign PDFs in 2 minutes at ₹15 per signature.

LinkedIn →

Product

  • Aadhaar eSign
  • Pricing
  • Templates
  • Rent Agreement eSign
  • Verify Signature
  • eSign Quiz
  • API
  • API Docs

Company

  • About
  • eSign Guide
  • Blog
  • Press
  • FAQ
  • Contact
Powered by eMudhra (CCA-licensed ESP)·IT Act 2000 Compliant·Aadhaar OTP Authenticated·Made in India 🇮🇳

© 2026 BN Habitat Pvt Ltd·CIN: U45400CH2010PTC043443·GST: 03AAECB5185C1Z3

Regd. Office: H.NO. 3355, 2nd Floor, Sector 37-D, Chandigarh, Chandigarh - 160036

Op. Office: Office 34, 13th Floor, Sushma Infinium, Chandigarh Ambala Expressway, Zirakpur, Punjab - 140603

TermsPrivacyRefundCookie