Current server time: 2018-11-14T17:46:38


This is an API for developing services that use the solutions provided by It is designed to be easy to use, while maintaining security. The API is open to all users of, and consists of both a platform independent REST API and a client code library in .NET. The code library is available as a NuGet package for .Net 4.0 and .Net 3.5, and can be downloaded here: 4.0 version, 3.5 version. We also have a VB6 client library, you can read more about it here to download it here: VB6 library.

In the other tabs above, documentation follows for the resources provided by the REST API, as well as information about which http headers that are required in order to make valid requests to the API. Also, all requests must be supplied with a token to authenticate the user. This token must be generated in a specific way. In the security tab it is explained how to generate this token, and there is an example in pseudocode of how to implement the generation.

In the tab with client code examples, we use the .NET client library to perform some basic operations on a document.

REST methods

Click on the resource name to expand.

POST{OldPrimaryKey} Renews the primary API key. Generates, sets and returns a new primary API key.
POST{OldSecondaryKey} Renews the secondary API key. Generates, sets and returns a new secondary API key.
POST{ProviderId}/OTPCode/{OTPCode} Generates a new primary key and returns it.
PUT Sends an OTP code in an SMS to the given mobile number (the input parameter) to be used in RenewPrimaryKeyOTPStep2 for renewing the primary API key. Use this method when the original primary API key is lost or unrecoverable.
GET{documentId}&signeeRefId={signeeRefId} Returns the url to sign the document for the given Signeeref or the first Signeeref if not SigneerefId is specified
GET{DocumentId} Retrieves the document with the given ID.
GET{DocumentId} Returns a temporary URL for viewing a signed document in the BankID applet.
GET{Status}&Fromdate={Fromdate}&JobId={JobId}&CreatedAfter={CreatedAfter}&ExternalCustomerRef={ExternalCustomerRef} Retrieves a list of documents base on the given parameters. All parameters are optional when not specifying any parameters the 200 last documents will be returned.
POST Creates a new document to sign, and returns a document response object (including the generated document ID). Remark: To create a new document, one must assign an already existing document job to it or generate a new one.
POST Cancels the given document (the document is then still available for the signee, but no longer marked as ready for signature). Remark: if using Json, a GUID must not contain dashes (-), unlike XML.
PUT Changes the signature deadline for a given document (after expiration date, the receiver is no longer allowed to sign the document).
POST Converts documents (doc, docx, txt, rtf and openoffice documents to PDF. Uses multipart form upload (ordinary http file upload)
GET{DocumentId} Returns the signed document as a file. Filename formatted as: {DocumentId}.sdo
GET{DocumentId} Returns the unsigned document as a file. Filename formatted as: {DocumentId}.pdf
GET{DocumentId} Returns the signed pdf document as a file. Filename formatted as: {DocumentId}.pdf
POST Creates a temporary url to a document (PDF, SDO, and more) that expires at a certain datetime
GET{jobid} Retrieves a document job in the form of a response object containing the document job parameters. Remark: if using Json, a GUID must not contain dashes (-), unlike XML.
POST Creates a document job (every document must be assigned to a document job). Returns the ID (GUID) for the created document job.
GET{ProviderId} Retrieves a document provider account (information such as the provider's username, billing address etc). Remark: if using Json, a GUID must not contain dashes (-), unlike XML.
GET Gets the expires date for your BankID certificate. If you don't have your own BankID certificate it will return Bad request.
GET{ProviderId} Retrieves usage for this account when using av prepaid account, what used, whats left
GET{ProviderId} Retrieves usage for this account when using av demo account, what used, whats left
POST Creates a new document provider (account for submitting documents). Returns the account ID and the primary and secondary API keys.
PUT Updates the information stored in a given document provider account, such as the billing address, logo file etc. Note that in contrast to the DocumentProvider POST method to create a document provider account, only the provider ID is required in this method. Only non-empty fields are updated. Remark: if using Json, a GUID must not contain dashes (-), unlike XML.
GET Returns the EventsQueue encryptionKey as a base64 encoded string
GET{DocumentId} Get the URLs to sign the Document.
GET{DocumentId}/{Domain}/{Language} Get the URLs to view a viewerapplet in a iFrame on your site.
GET{SigneeRefId} Get status of the BankID mobile Sign session
PUT Creates a app launch uri for the BankID app (iOS and Android) for signing a document for given signeeref
PUT Starts a BankID mobile sign session for the given document, with given mobilenumber and date of birth. Returns the BankID mobile reference "Snill bank"
GET Gets all forms to the authenticated documentprovider
GET{formId}&fromDate={fromDate}&toDate={toDate} Gets all signed forms to the authenticated documentprovider. Can filter results by applying the imputparameters.
GET{formId}&FormSignatureId={FormSignatureId}&AttatchmentReference={AttatchmentReference} Gets the attachements to the form.
GET{documentid} Gets a signed form from DocumentID
GET{formId}&formSessionId={formSessionId} Gets a signed form from formId and formSessionId
GET{documentId}&formSessionId={formSessionId}&signeeRefId={signeeRefId} Returns the url to sign the (form) document for the given Signeeref
PUT{formId} Enables the form
PUT{formId} Disables the form
GET{year}/{month} Returns a list of invoice transactions for the given month
POST{DealerId} Parses a license file and returns accountinformation to use in your app/website
GET{MessageId} Gets details for a specific message. Remark: if using Json, a GUID must not contain dashes (-), unlike XML.
GET{DocumentId} Retrieves a list of all the messages that are sent for the given document. Remark: if using Json, a GUID must not contain dashes (-), unlike XML.
POST Sends a message to the signees of a given document. Returns HTTP status code "created" if the message was successfully created and distributed. Remark: if using Json, a GUID must not contain dashes (-), unlike XML.
POST Sends a message to an external person with a link/URL to view a document. The external person will receive an OTP code via SMS (to the given mobile number) to access the document on the issued URL.
PUT Sends a new message to the Signeeref if the first one failed, can also be sendt to a different email address.
DELETE{ProviderId}/{ReceiverId} Deletes a given receiver
DELETE{ProviderId} Deletes all the receivers for this provider
GET{ReceiverId}?ProviderId={ProviderId} Returns the given receiver
GET{ProviderId} Returns alle the receivers registered to the provider
POST Creates a receiver for this provider
POST No Documentation Found.
GET{RequestId}?metadata={metadata} Retrives a SignereID session to get the information aboute the authorized user
GET{RequestId} Check if a SignereID session is completed or not, used mainly for BankID mobile when the GUI is self hosted
POST DEPRECATED goto for our new authentication api Creates a SignereID request, and returns a url. This url can be used in an iFrame (if the iFrame property is set) or used in a redirect. Example url: To detect if user is on a mobile device check out To check for tablet add check for ipad/android or mobile in the useragent string. The login will automaticly get status LOGINTIMEDOUT 5 minutes after successfull login Use this javascript if you use WebMessaging
PUT Invalidates a SignereID request (set the operationstatus to LOGININVALIDATED) to prevent replay attacks
GET{Year}&Month={Month}&Day={Day}&Status={Status} Returns a statistics response object with various information.
GET Returns the UTC time of the server
GET{request} Send in a Unique string and check if you get the same one in return, this checks that the service is operativ. It requires the HTTP header: PingToken and a ping token (this you can get from support) this to limit access to this feature.

REST HTTP headers

All REST resources in this API demand that the HTTP request contains certain headers. The relevant headers are listed below. In the description of each header, it is indicated whether it is required or optional. There is also a description of the expected format of each header and an example of a valid header.

Header: API-ID

This is the unique identification for the document provider's API account. The ID is necessary in order for to authenticate the request. Required API-ID: 2d0193b6-5dcb-4f74-b6da-a0b500dc18d0


The API-TOKEN header should contain a hash where one uses one of the two account keys and some other parameters depending on the request type (see the API security tab for an explanation of the token generation algorithm). Since the account keys are secret, it is very important that they are not passed directly in the header. Required API-TOKEN: FD714617939D4BB01C47BD959EEF911B1BC53...


This is the timestamp for when the request was sent. The server checks the timestamp, and denies access to the resources if the request timestamp deviates more than 5 minutes from server time. The header timestamp should be the time in UTC, complying with the ISO8601 formatting standard. The timestamp should be the same as the one used to generate the API token. Required API-TIMESTAMP: 2012-09-21T12:40:26
This header indicates whether one is using the primary or secondary key in the API-TOKEN. By default, the server assumes that the primary key is used, and tries to match the hash with the hashed primary key. Therefore, this header must be included and set to true if the secondary key is used instead. Optional API-USINGSECONDARYTOKEN: false


This header specifies which encryption algorithm that was used to generate the API-TOKEN header. By default, the server assumes that one is using a 256 bit HMAC SHA encryption (SHA256). If one uses another algorithm, this must be specified here. Optional API-ALGORITHM: SHA512
In some cases it can be convenient to receive error messages from the server in the headers instead of the body. This could be the case if one catches a web exception and does not have access to the response body. If this header is set to true, a string with all error messages will be returned in the response headers. Optional API-RETURNERRORHEADER: true

API security

The security of the API lies in the communication between client and server, and authentication of requests on the server. All communication between the client and the REST server is transported using the HTTPS protocol, which prevents eavesdropping and man-in-middle attacks.

Furthermore, the API uses a set of private keys to authenticate users. For each API account, issues two keys and one ID. The ID identifies the account itself, but does not give access without authentication. The primary key gives access to all resources that are available in the API, whereas the secondary key only gives access to day-to-day services. These keys are secret to the public. From the keys, the contents, timestamp and HTTP verb, one must generate a hashed token which is passed as a header in the HTTP request. The server will know which key that belongs to the client’s user account based on the API ID. To authenticate the request, the server will re-generate the token and compare it with the received one to authenticate the client.

The token generation algorithm is based on the SHA256 or SHA512 cryptographic hash functions. For GET requests, the API-TOKEN should be a hash of the resource URL and the timestamp that is passed in API-TIMESTAMP, and either the primary or secondary account key should be used as key for the encryption algorithm. The string that should be hashed is on the form "URL&Timestamp=API-TIMESTAMP&Httpverb=HTTPVERB", where URL is the request URL, API-TIMESTAMP is the passed timestamp and HTTPVERB is the HTTP verb being used, written in uppercase (either GET or DELETE).

For POST and PUT requests, the entire message body (JSON or XML string) should be hashed together with the timestamp. The string that is hashed should be on the form MESSAGE_JSON_STRING{Timestamp:"API-TIMESTAMP",Httpverb:"POST/PUT"} for JSON contents, where MESSAGE_JSON_STRING is the message body in the request (including curly brackets) and API-TIMESTAMP is the passed timestamp. For XML contents it should be on the form MESSAGE_XML_STRING<Timestamp>API-TIMESTAMP</Timestamp><Httpverb>POST/PUT</Httpverb>, where MESSAGE_XML_STRING is the message body (including angle brackets).

Note that the string in the JSON case includes quotes around the timestamp and the HTTP verb, whereas the string in the XML case does not.

For clarity, the token generation routines are given in pseudocode below. Quotes inside a string are escaped with “\"”, and the hash is computed with the HMAC SHA512 algorithm.

function GenerateApiToken_GET_DELETE(url, accountKey, timestamp) {

      declare variable urlWithTimeStamp;

      set urlWithTimeStamp to url +“&Timestamp=” +timestamp” +”&Httpverb=GET/DELETE”; 

      return GetSHA512(urlWithTimeStamp, secretKey)


function GenerateToken_POST_PUT_JSON(jsonString, accountKey, timestamp) {

      declare variable jsonWithTimeStampAndHttpverb; 

      set jsonWithTimeStampAndHttpverb to jsonString+”{Timestamp:” + “\”” + timestamp + “\”,Httpverb:\”POST/PUT\”” + “}”;

      return GetSHA512(jsonWithTimeStampAndHttpverb, accountKey);


function GenerateToken_POST_PUT_XML(xmlString, accountKey, timestamp) {

      declare variable xmlWithTimeStampAndHttpverb;

      set xmlWithTimeStamp to xmlString+ “<Timestamp>” + timestamp + “</Timestamp>”+”<Httpverb>”+”POST/PUT”+”</Httpverb>”;

      return GetSHA512(xmlWithTimeStampAndHttpverb, accountKey);


function GetSHA512(text, accountKey) {

      use accountKey as key in HMAC SHA512 algorithm;

      compute SHA512Hash from text;

      return SHA512Hash;


API terms and keywords

In the world of, a number of special terms are used. In the following we present the most common terms and keywords used in the API and give an explanation of their applications in for instance the API data model.

API ID: A unique identifier (GUID) for a user account.

API key: A private key that is used to authenticate requests to through the API. An API key should never be shared outside of the organization that owns the user account.

Document provider: A document provider is any organization or person registered as a user on The term is sometimes used loosely about the user that uploads documents, but in principle it refers to the organization/person that owns a user account at To each document provider, there is associated an API ID and two API keys.

Document job: A document job is an abstraction of the process of issuing documents belonging together, and is used as a data model object in the API. To exemplify, think about a user working with a specific customer, requiring the customer to sign a set of documents in order to settle an agreement. For the specific process and the given customer, these documents logically belong together. By assigning the documents to the same document job, all documents are linked to the same contact person with the document provider.

Document file: A document file is, as the name suggests, the very data file of a document. In the context of the client library, it is an object which also contains some metadata about the data file, like the name of the file, the document ID and the date of creation. In the context of the API resource DocumentFile, it is the object returned when the user requests either a signed or unsigned document.

SigneeRef: In the API, a SigneeRef models a person who is supposed to sign a document. It includes parameters like the name, e-mail address etc. In contrast to a Signee, the identity of a SigneeRef is not necessarily verified. For instance, when creating a document for signature, the SigneeRefs listed in the request are the persons that are supposed to sign the document, but when they have signed, they become Signees in the API model.

Signee: A signee is a person who has signed a document, and where the identity is verified with BankID. A Signee object has a one-to-one correspondence with a particular signature. The time of signature and the BankID PID (personal identifier) used in the signature are contained in it.

Receiver: A receiver is a person or organization to which one intends to issue documents more than once. By creating a receiver through the API (or in the portal), one can store and retrieve information about returning customers instead of having to type the information every time a document is to be issued.

External signature: It is possible to perform the process of signature on your own site instead of letting the signee use the portal, which in our terminology is called an external signature. To do so, one can make a request to the resource ExternalSign and integrate the process into an <iframe> (see the resource documentation for more details). 

External login: Just as with signatures, it is possible to integrate BankID on your own site through the API and let your users log in to your services by means of the BankID authentication. We call this an external login. To do so, one can make a request to the resource ExternalLogin and integrate the process into an <iframe> (see the resource documentation for more details). 

FromURI: In the API documentation, for each method the parameters in the request are listed, and at the end it is indicated whether the parameter is passed in the URI or in the body. FromURI indicates that the parameter is read from the URI.

FromBody: In the API documentation, for each method the parameters in the request are listed, and at the end it is indicated whether the parameter is passed in the URI or in the body. FromBody indicates that the parameter is read from the body of the HTTP request.

Client code examples

We present an example of a basic console application written in C# that uses the .NET client library.

The program uploads a document to the server, which notifies the signee that he/she has received a new document. Then, the program downloads the signed document (assuming that the document has been signed).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Unipluss.Sign.Client.Models;
using Unipluss.Sign.ExternalContract.Entities;
namespace SignereClientConsoleDemo
class Program
private const string url = "";
private const string apiId = "eb09fc43f16c44e9b9a4a149009834c9";
//Can be obtained from "min side"
private const string primaryKey = "bjRXV2RrYmNWUHNKRXR1T1J5ZXpRZz09LGxOaTU0VlFNeGVGTEZ
//Can be obtained from "min side"
private const string filePath = @@"C:\signeredemo.pdf";
private const string filePathSigned = @@"C:\signeredemo.sdo";
static void Main(string[] args){
var client = new Unipluss.Sign.Client.Client(url, apiId, true, true);
Console.WriteLine("Sending data");
Document result = client.CreateSingleDocument(CreateDocument(), filePath,
Console.WriteLine("Data received from server");
Console.WriteLine("Click when the document is signed");
Document signedDocument = client.GetDocument(result.Id, primaryKey);
var receiver = signedDocument.SigneeRefs.FirstOrDefault();
Console.WriteLine("Signed {0}, by: {1} date of birth: {2}",
client.DownloadSignedDocument(result.Id, filePathSigned, primaryKey);
//Provide your own test data
private static NewSingleDocument CreateDocument() {
var mottaker = new SigneeRef()
FirstName = "Ola",
LastName = "Normann",
CompanyName = "Normann AS",
Email = "",
ExternalSigneeId = "100500",
Mobile = "+4744332211",
SocialSecurityNumber = "07128312345",
OrgNo = "987654321"
var doc = new NewSingleDocument()
Contact_Email = "",
Contact_Mobile = "+4799887766",
Contact_Name = "John Doe",
Contact_Phone = "+4755443322",
Contact_Url = "",
CreatedByApplication = "Demo console app",
Description = "Test document from console",
ExternalDocumentId = "demo ref",
Language = NewSingleDocument.Languages.EN,
MessageEmail = "Hello! Please click this link to sign: {signlink}",
Title = "Title of demo document " + DateTime.Now.ToString(),
TopicEmail = "E-mail topic",
SigneeRefs = new List<SigneeRef>(),
return doc;
public static string SerializeObjectToString<T>(T T_object) {
var flags = BindingFlags.Instance | BindingFlags.Public |
PropertyInfo[] infos = T_object.GetType().GetProperties(flags);
StringBuilder sb = new StringBuilder();
string typeName = T_object.GetType().Name;
sb.AppendLine(String.Empty.PadRight(typeName.Length + 5, '='));
foreach (var info in infos) {
object value = info.GetValue(T_object, null);
sb.AppendFormat("{0}: {1}{2}", info.Name, value != null ? value : "null",
return sb.ToString();