signnow/api-php-sdk

Library gives you ability to communicate with SignNow API


README

Simple API Client to integrate SignNow with your application or website. Sign documents, request e-signatures, and build role-based workflows with multiple signers: https://www.signnow.com/developers

Table of Contents

  1. Requirements
  2. Install
  3. Setting up
  4. Tests
  5. Sandbox
  6. Entity manager
  7. Actions
  8. Examples & use cases

Requirements

PHP 7.1 or newer

Install

composer require signnow/api-php-sdk

Setting up

Register an annotation loader if only there is doctrine/annotations less v2.0 in use. This method is deprecated and will be removed in doctrine/annotations 2.0 so annotations will be autoloaded in 2.0.

AnnotationRegistry::registerLoader('class_exists');

Create the instance of Entity Manager:

use SignNow\Api\Service\Factory\EntityManagerFactory;
use SignNow\Api\Service\Factories\TokenFactory;

// configuring entity manager with the basic token 
$entityManager = 
    (new EntityManagerFactory())->create(
         'https://api.signnow.com',
         (new TokenFactory())->basicToken('YOUR_BASIC_TOKEN_STRING')
     );
use SignNow\Api\Service\Factory\EntityManagerFactory;
use SignNow\Api\Service\Factories\TokenFactory;

// configuring entity manager with the bearer token
$entityManager = 
    (new EntityManagerFactory())->create(
         'https://api.signnow.com',
         (new TokenFactory())->bearerToken('BEARER_TOKEN_STRING')
     );

Setup update http method for Entity Manager:

use SignNow\Rest\Http\Request;

$entityManager->setUpdateHttpMethod(Request::METHOD_PUT);

Also, it is possible to use the wrapper using OAuth authorization

use SignNow\Api\Action\OAuth as SignNowOAuth;

$auth = new SignNowOAuth('https://api.signnow.com');

$entityManager = $auth->bearerByPassword('YOUR_BASIC_TOKEN_STRING', 'username', 'password');

Tests

SignNow PHP SDK is covered with functional tests using Codeception and Phiremock. Phiremock allows us to mock calls to SignNow API. All the calls pass at 127.0.0.1 port 8008. Ensure that this port is not in use in the local machine before running test.

All the tests execution in console:

vendor/bin/codecept run functional

A single test execution in console:

vendor/bin/codecept run tests/functional/Template/CreateCest.php

Also, tests might be useful as examples of using SignNow PHP SDK.

Sandbox

Directory sandbox contains php script to taste some SDK feature. Please, provide this scripts with your personal credentials, write some code or use existing code. Execute sandbox script in console:

php sandbox/execute.php

Entity manager

Entity manager is the main class which controls communication with 3rd party REST API where JSON is used as main data type. It's responsible for saving objects to and fetching objects from the API.

Each entity is described by:

  • API resource url (via HttpEntity annotation),
  • API payload (via properties and theirs types),
  • API response type (via ResponseType annotation, optional).

Examples & use cases

Upload Document to SignNow

use SignNow\Api\Entity\Document\Upload as DocumentUpload;

$uploadFile = (new DocumentUpload(new \SplFileInfo('realFilePath')));
$document = $entityManager->create($uploadFile);

Download Document from SignNow

use SignNow\Api\Entity\Document\Download as DocumentDownload;

$documentUniqueId = 'e896ec9311a74a8a8ee9faff7049446fe452e461';

$document = $entityManager->get(
    new DocumentDownload(),
     [
        'id' => $documentUniqueId,
     ],
     [
        'type' => 'collapsed',
     ]);

Actions

Actions - this is just a new abstraction layer above Entity Manager and implemented as services. So that, both Entity Manager and Actions are equivalent options to use SignNow API. See actions in directory src/Action.

OAuth 2.0

Request Access Token

use SignNow\Api\Entity\Auth\TokenRequestPassword;

$entityManager->create(new TokenRequestPassword($username, $password));

Verify Access Token

use  SignNow\Api\Entity\Auth\Token;

$entityManager->get(Token::class);

Refresh Access Token

use SignNow\Api\Entity\Auth\TokenRequestRefresh;

$entityManager->create(new TokenRequestRefresh($refreshToken));

Document

Upload document

use SignNow\Api\Entity\Document\Upload as DocumentUpload;

$entityManager->create(new DocumentUpload(new \SplFileInfo($filePath)));

Upload document with text tags & convert them to fillable fields

use SignNow\Api\Entity\Document\FieldExtract;

$entityManager->create(new FieldExtract(new \SplFileInfo($filePath)));

Retrieve document

use SignNow\Api\Entity\Document\Document;

$documentUniqueId = 'e896ec9311a74a8a8ee9faff7049446fe452e461';

$entityManager->get(new Document(), ['id' => $documentUniqueId]);

Delete document

use SignNow\Api\Entity\Document\Document;

$documentUniqueId = 'e896ec9311a74a8a8ee9faff7049446fe452e461';

$entityManager->delete(new Document(), ['id' => $documentUniqueId]);

Download document

use SignNow\Api\Entity\Document\Download as DocumentDownload;

$documentUniqueId = 'e896ec9311a74a8a8ee9faff7049446fe452e461';

$entityManager->get(new DocumentDownload(), ['id' => $documentUniqueId], ['type' => 'collapsed']);
// type can be 'collapsed' or 'zip' 

// if need table containing the document's history set with_history=1
$entityManager->get(new DocumentDownload(), ['id' => $documentUniqueId], ['type' => 'collapsed', 'with_history' => 1]);

Modify document name

use SignNow\Api\Action\Document;
use SignNow\Api\Action\OAuth as SignNowOAuth;

$auth = new SignNowOAuth(HOST);
$entityManager = $auth->bearerByPassword(
    BASIC_TOKEN,
    USER,
    PASSWORD
);

$documentUniqueId = 'd136ce0211a74a808de9fefe7249446fe452e566';
$documentName = 'Your document name to be modified';

$document = new Document($entityManager);
$documentEntity = $document->modifyName($documentUniqueId, $documentName);

Create a single-use link for document downloading

use SignNow\Api\Entity\Document\DownloadLink;

$documentUniqueId = 'e896ec9311a74a8a8ee9faff7049446fe452e461';
$entityManager->create(new DownloadLink(), ['id' => $documentUniqueId])

Create a role-based invite to sign a document

use SignNow\Api\Action\Document;
use SignNow\Api\Entity\Document\Field\TextField;
use SignNow\Api\Action\Invite\FieldInvite;
use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Entity\Invite\Invite;

$auth = new SignNowOAuth(HOST);
$entityManager = $auth->bearerByPassword(
    BASIC_TOKEN,
    USER,
    PASSWORD
);

$document = new Document($entityManager);
$textField = (new TextField())
   ->setName('My test text')
   ->setLabel('Some label')
   ->setPrefilledText('prefilled text')
   ->setPageNumber(0)
   ->setRole($role)
   ->setRequired(true)
   ->setHeight(20)
   ->setWidth(10)
   ->setX(100)
   ->setY(150);
$document->addFields($documentUniqueId, [$textField]);

$from = 'sender@domain.com';
$to[] = new Recipient(
   'signer1@domain.com',
   'Role 1',
   '488d73a3efab032511f144af3a2572a8aae20162',
   1,
   null,
   'Signing request',
   'We are waiting for your signature'
);
$to[] = new Recipient(
   'signer2@domain.com',
   'Role 2',
   'e896ec9311a74a8a8ee9faff7049446fe452e461',
   2,
   15,
   'Sign me',
   'Please, sign this document'
);
$cc = [];

// using action FieldInvite
// is more preferable way
// to create an invitation
$fieldInvite = new FieldInvite($entityManager);
$response = $fieldInvite->create($documentUniqueId, $from, $to, $cc);

// or
// using entity Invite still works as well
$invite = new Invite($from, $to, $cc);
$response = $entityManager->create($invite, ["documentId" => $documentUniqueId]);

Create a simple free form invite to sign a document

use SignNow\Api\Entity\Invite\Invite;
use SignNow\Api\Entity\Invite\Recipient;

$documentUniqueId = 'd9b490bd613e25cc5ec1a3b0b83dfccc164382bd';
$signerEmail = 'signer@domain.com';
$roleName = 'Manager';
$roleUniqueId = '488d73a3efab032511f144af3a2572a8aae20162';
$from = 'My Application <no-reply@domain.com>';

$to[] = (new Recipient($signerEmail, $roleName, $roleUniqueId))
            ->setSubject($subject)
            ->setMessage($message);

$invite = new Invite($from, $to, $cc);

$entityManager->create($invite, ["documentId" => $documentUniqueId]);

Cancel an invite to sign a document

use SignNow\Api\Entity\Invite\CancelInvite;
use SignNow\Rest\Http\Request;

$entityManager
    ->setUpdateHttpMethod(Request::METHOD_PUT)
    ->update(new CancelInvite(), ['documentId' => $documentUniqueId]);

Create a signing link

use SignNow\Api\Entity\Invite\SigningLink;

$entityManager->create(new SigningLink($documentUniqueId));

Add fillable fields to a document

use SignNow\Api\Entity\Document\Document;
use SignNow\Api\Entity\Document\Field\SignatureField;
use SignNow\Api\Entity\Document\Field\TextField;

$signatureField = (new SignatureField())
    ->setName('My Signature')
    ->setPageNumber(0)
    ->setRole('role 1')
    ->setRequired(true)
    ->setHeight(20)
    ->setWidth(10)
    ->setX(5)
    ->setY(10);

$textField = (new TextField())
    ->setName('My text')
    ->setLabel('Some label')
    ->setPrefilledText('prefilled text')
    ->setPageNumber(0)
    ->setRole('role 1')
    ->setRequired(true)
    ->setHeight(20)
    ->setWidth(10)
    ->setX(100)
    ->setY(150);

$document = (new Document())
    ->setId($documentUniqueId)
    ->setFields([$signatureField, $textField]);
               
$entityManager->update($document);

Prefill text fields

use SignNow\Api\Action\PrefillTextFields;
use SignNow\Api\Entity\Document\PrefillText\FieldRequest;

$prefill = new PrefillTextFields($bearer);
    
$fields = [];
$fields[] = (new FieldRequest())
   ->setFieldName('Document')
   ->setPrefilledText('Agreement #12-820/01');

$prefill->prefill($documentUniqueId, $fields);

Fill smart fields

use SignNow\Api\Action\FillSmartFields;
use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Entity\Document\SmartField\SmartField;

$auth = new SignNowOAuth(HOST);
$entityManager = $auth->bearerByPassword(
    BASIC_TOKEN,
    USER,
    PASSWORD
);

$prefill = new FillSmartFields($bearer);
    
$fields = [['Country' => 'USA'], ['City' => 'Boston']];
$smartFields = (new SmartField())->setFields($fields);
$smartFields->addField('key', 'value');

$prefill->fill($documentUniqueId, $smartFields);

Move document

use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Action\MoveDocumentAction;
use SignNow\Api\Entity\Document\MoveDocument\MoveDocument;

$auth = new SignNowOAuth(HOST);
$entityManager = $auth->bearerByPassword(
    BASIC_TOKEN,
    USER,
    PASSWORD
);

$moveDocumentEntity = new MoveDocument();
$moveDocumentEntity->setFolderId($folderId);

$moveDocumentAction = new MoveDocumentAction($entityManager);
$moveDocumentAction->move($documentUniqueId, $moveDocumentEntity);

Template

Create a template

use SignNow\Api\Entity\Template\Template;

$template = (new Template())
    ->setDocumentId($documentUniqueId)
    ->setDocumentName('My document name');
 
$entityManager->create($template);

Generate a document from template (Copy template)

use SignNow\Api\Entity\Template\Copy as TemplateCopy;

$templateCopy = (new TemplateCopy())
        ->setTemplateId($templateId)
        ->setDocumentName('My document');

$entityManager->create($templateCopy);

Document group

Retrieve document group

use SignNow\Api\Entity\DocumentGroup\DocumentGroup;

$entityManager->get(
    (new DocumentGroup())
        ->setGroupName('my group')
        ->setId($documentGroupId)
        ->setDocuments($documentsArray)
);

Delete document group

use SignNow\Api\Entity\DocumentGroup\DocumentGroup;

$entityManager->delete(new DocumentGroup(), ['id' => $documentGroupId]);

Cancel document group invite

use SignNow\Api\Entity\DocumentGroup\GroupInvite\Cancel as DocumentGroupInviteCancel;

$entityManager->create(
    new DocumentGroupInviteCancel(),
    [
        'documentGroupId' => $documentGroupId,
        'groupInviteId' => $groupInviteId,
    ]
);

Event subscriptions

Get User Event Subscriptions

use SignNow\Api\Entity\EventSubscription\GetEventSubscriptions;

$entityManager->get(new GetEventSubscriptions());

Create User Event Subscription

use SignNow\Api\Entity\EventSubscription\CreateEventSubscription;

$entityManager->create(
    (new CreateEventSubscription())
    ->setEvent('document.update')
    ->setCallbackUrl('https://google.com.ua')
);

Delete User Event Subscription

use SignNow\Api\Entity\EventSubscription\DeleteEventSubscription;

$entityManager->delete(
    new DeleteEventSubscription(),
    ['uniqueId' => $uniqueId]
);

Embedded Invites

Create embedded invites

use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Action\EmbeddedInvite;
use SignNow\Api\Entity\Embedded\Invite\InviteRequest;
use SignNow\Api\Service\OAuth\AuthMethod\Method\None;

$auth = new SignNowOAuth('https://api.signnow.com');

$embedInvite = new EmbeddedInvite(
  $auth->bearerByPassword('YOUR_BASIC_TOKEN', 'user', 'password')
);

$invites[] = (new InviteRequest())
     ->setEmail('name.surname@domain.com')
     ->setRoleId('4d4122e8574b4462a67505c0a89c6015780518f1')
     ->setOrder(1)
     ->setAuthMethod(new None())
     ->setFirstName('Name')
     ->setLastName('Surname');

$embeddedInvites = $embedInvite->create(DOCUMENT_UID, $invites);

foreach ($embeddedInvites->getInvites() as $invite) {
  echo $invite->getId() , PHP_EOL,
     $invite->getEmail() , PHP_EOL,
     $invite->getRoleId(), PHP_EOL,
     $invite->getOrder(), PHP_EOL,
     $invite->getStatus(), PHP_EOL,
     PHP_EOL;
}

Create signing link

use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Action\EmbeddedInvite;

$auth = new SignNowOAuth('https://api.signnow.com');

$embedInvite = new EmbeddedInvite(
  $auth->bearerByPassword('YOUR_BASIC_TOKEN', 'user', 'password')
);

$documentUniqueId = '0d3122a857514462a67515c0a39c6015780518f2';
$inviteUniqueId = '3313c8fb12594004babb98a5f7418c11ad572b05';
echo $embedInvite->createSigningLink($documentUniqueId, $inviteUniqueId)->getLink();

Prolong signing link

use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Action\EmbeddedInvite;

$auth = new SignNowOAuth('https://api.signnow.com');

$embedInvite = new EmbeddedInvite(
  $auth->bearerByPassword('YOUR_BASIC_TOKEN', 'user', 'password')
);

$expiration = 45;
$documentUniqueId = '0d3122a857514462a67515c0a39c6015780518f2';
$inviteUniqueId = '3313c8fb12594004babb98a5f7418c11ad572b05';
echo $embedInvite->setSigningLinkExpiration($documentUniqueId, $inviteUniqueId, $expiration)->getLink();

Delete embedded invites

use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Action\EmbeddedInvite;

$auth = new SignNowOAuth('https://api.signnow.com');

$embedInvite = new EmbeddedInvite(
  $auth->bearerByPassword('YOUR_BASIC_TOKEN', 'user', 'password')
);

$documentUniqueId = '0d3122a857514462a67515c0a39c6015780518f2';
$embedInvite->delete($documentUniqueId);

Reassign signers

User

Upload Initials

use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Action\User\Initial as UserInitial;

$auth = new SignNowOAuth('https://api.signnow.com');
$initial = new UserInitial(
  $auth->bearerByPassword('YOUR_BASIC_TOKEN', 'user', 'password')
);

$userInitialBase64EncodedImage = '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';
$entity = $initial->upload($userInitialBase64EncodedImage);

echo $entity->getId(), PHP_EOL,
    $entity->getWidth(), PHP_EOL, 
    $entity->getHeight(), PHP_EOL;

Get Initials

use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Action\User\Initial as UserInitial;

$auth = new SignNowOAuth('https://api.signnow.com');
$initial = new UserInitial(
  $auth->bearerByPassword('YOUR_BASIC_TOKEN', 'user', 'password')
);

$entity = $initial->get();

$signatureImage = base64_decode($entity->getData());

echo $entity->getId(), PHP_EOL,
    $entity->getWidth(), PHP_EOL, 
    $entity->getHeight(), PHP_EOL;

Upload Signature

use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Action\User\Signature as UserSignature;

$auth = new SignNowOAuth('https://api.signnow.com');
$signature = new UserSignature(
  $auth->bearerByPassword('YOUR_BASIC_TOKEN', 'user', 'password')
);

$userSignatureImage = file_get_contents('/path/to/image');
$userSignatureBase64EncodedImage = base64_decode($userSignatureImage);
$entity = $signature->upload($userSignatureBase64EncodedImage);

echo $entity->getId(), PHP_EOL,
    $entity->getWidth(), PHP_EOL,
    $entity->getHeight(), PHP_EOL;

Get Signature

use SignNow\Api\Action\OAuth as SignNowOAuth;
use SignNow\Api\Action\User\Signature as UserSignature;

$auth = new SignNowOAuth('https://api.signnow.com');
$signature = new UserSignature(
  $auth->bearerByPassword('YOUR_BASIC_TOKEN', 'user', 'password')
);

$entity = $signature->get();

$signatureImage = base64_decode($entity->getData());

echo $entity->getId(), PHP_EOL,
    $entity->getWidth(), PHP_EOL,
    $entity->getHeight(), PHP_EOL;