Portal flow

This integration pattern is suitable for senders who want to create a signature job in portal flow. The signer logs in to the signing portal, signs the document, and the sender will then be able to poll for a status and retrieve the signed document. This scenario is designed to support a flow where it is necessary to obtain signatures from more than one signer.

To ease the integration, we provide C# and Java libraries. If you are creating your own client, you will have to interact directly with the API. The message format of the API is XML, and relevant types can be found in portal.xsd.

Flytskjema for portalintegrasjon

Flow chart for signing in portal flow: The chart shows that a sender creates a signature job, starts polling, signers signing the job, a status update is fetched by polling by the sender, followed by downloading the signed document. If you send only one job to one signer, please disregard the first “steg 4”-section. Solid lines show user flow and dashed lines shows requests to and responses from the API.

Having problems integrating?

Tip

Remember that if you are having problems creating a job in a portal signature flow, you can always get in touch with a developer on Github:

Get help for your C# integration here.

Step 1: Create signature job

ClientConfiguration clientConfiguration = null; //As initialized earlier
var portalClient = new PortalClient(clientConfiguration);

var documentsToSign = new List<Document>
{
    new Document(
        "Document title",
        FileType.Pdf,
        @"C:\Path\ToDocument\File.pdf"
    )
};

var signers = new List<Signer>
{
    new Signer(new PersonalIdentificationNumber("00000000000"), new NotificationsUsingLookup()),
    new Signer(new PersonalIdentificationNumber("11111111111"), new Notifications(
        new Email("email1@example.com"),
        new Sms("999999999"))),
    new Signer(new ContactInformation {Email = new Email("email2@example.com")}),
    new Signer(new ContactInformation {Sms = new Sms("88888888")}),
    new Signer(new ContactInformation
    {
        Email = new Email("email3@example.com"),
        Sms = new Sms("77777777")
    })
};

var portalJob = new Job("Job title", documentsToSign, signers, "myReferenceToJob");

var portalJobResponse = await portalClient.Create(portalJob);

Note

You may identify the signature job’s signers by personal identification number IdentifiedByPersonalIdentificationNumber or contact information. When identifying by contact information, you may choose between instantiating a PortalSigner using IdentifiedByEmail, IdentifiedByMobileNumber or IdentifiedByEmailAndMobileNumber.

Addressing signers

It is helpful to familiarize yourself with Addressing signers and Notifications and contact details to understand the different ways a signer can be addressed and notified. All examples given below are not applicable for all kinds of senders, particularily there restrictions depending on whether the sender is a public or private sector organization.

Email address and/or mobile number

var signers = new List<Signer>
{
    new Signer(new ContactInformation {Email = new Email("email2@example.com")}),
    new Signer(new ContactInformation {Sms = new Sms("88888888")}),
    new Signer(new ContactInformation
    {
        Email = new Email("email3@example.com"),
        Sms = new Sms("77777777")
    })
};

National identity number

When identifying signers by their national identity number, you can specify which email address and/or mobile number should be used for for notifications.

var signers = new List<Signer>
{
    new Signer(
        new PersonalIdentificationNumber("11111111111"),
        new Notifications(
            new Email("email1@example.com"),
            new Sms("999999999"))),
    new Signer(
        new PersonalIdentificationNumber("22222222222"),
        new Notifications(
            new Email("email2@example.com")))
};

However, for public sector organizations, if the documents being signed are of a personal nature (e.g. not signed by virtue of a role in an organization) it is strongly advisable to have Posten signering inquiring The common contact register to lookup which methods the signer prefers to be notified. (This feature is not available at all for private sector organizations)

See also the section Signing on behalf of for information on signing on behalf of other entities (e.g. organizations).

var signers = new List<Signer>
{
    new Signer(
        new PersonalIdentificationNumber("11111111111"),
        new NotificationsUsingLookup { SmsIfAvailable = true }),
    new Signer(
        new PersonalIdentificationNumber("22222222222"),
        new NotificationsUsingLookup())
};

Signing on behalf of

A sender can specify if signers are signing on behalf of theirself (“self”, the default if not specified), or on behalf of or by virtue of a role (“other”).

In the case of signing on behalf of “other”, the features intended for private citizen services will not be available. This means:

  • The signed document will not be automatically forwarded to the signer’s private digital mailbox.

  • For public organizations, The common contact register will not be used, and the sender must provide the email address and/or mobile number to use for notifying the signer.

var signers = new List<Signer>
{
    new Signer(
        new PersonalIdentificationNumber("11111111111"),
        new NotificationsUsingLookup()),
    new Signer(
        new PersonalIdentificationNumber("22222222222"),
        new Notifications(new Email("email2@example.com")))
    {
        OnBehalfOf = OnBehalfOf.Other
    },
    new Signer(
        new ContactInformation { Email = new Email("email3@example.com") }),
    {
        OnBehalfOf = OnBehalfOf.Other
    }
};

Note

Public organizations collecting personal signatures should mainly address signers by their national ID, which mandates the use of Kontakt- og Reservasjonsregisteret for resolving their preferred contact information used for notifications of the signature job, and also to enforce their preference in case they opt-out from digital communication from the public sector.

Other settings

Order

The order attribute on signer is used to specify the order of the signers. In the example above, the signature job will only be available to the signers with order = "1". Once signed, the job becomes available to those with order = "2", and for the signer with order = "3" when those with order = "2" have signed.

Availability

The element availability is used to control the period of time a signature job is available to the signer(s).

<availability>
    <activation-time>2016-02-10T12:00:00+01:00</activation-time>
    <available-seconds>864000</available-seconds>
</availability>

The time specified in activation-time indicates when the job is activated, and the first signers are given the opportunity to sign the job. The duration specified in available-seconds applies to all signers. That is, all signers will have the same time to sign or reject the job from it becomes available to them. Thus, this period applies to each set of signers with the same order.

For example, enter 345600 seconds (4 days) for signers with an order:

  1. Signers with order = 1 get 4 days from `` activation-time`` to sign.

  2. Signers with order = 2 will have the document made available immediately when all signers with order = 1 have signed. They will then have 4 days from the time signature job is made available.

Note

If you omit availability, the job will be activated immediately, and the job will be available for a maximum of 30 days for each set of order grouped signers.

Important

A signature job expires and stops if at least one signer does not sign within their time period when the job is available.

Important

Jobs that specify greater available-seconds than 7,776,000 seconds (90 days) are rejected.

Identifier in the signed document

The element identifier-in-signed-documents is used to specify how signers are to be identified in the signed documents. Allowed values are PERSONAL_IDENTIFICATION_NUMBER_AND_NAME, DATE_OF_BIRTH_AND_NAME and NAME, but not all are valid for all types of signature jobs and senders. For more information, see How are signers identified in a signed document?.

Note

You can specify a signature type and required authentication level. If signature type or required authentication level is omitted, default values will be set as specified by Signature type and Security level.

List<Document> documentsToSign = null; //As initialized earlier
var signers = new List<Signer>
{
    new Signer(new PersonalIdentificationNumber("00000000000"), new NotificationsUsingLookup())
    {
        SignatureType = SignatureType.AdvancedSignature
    }
};

var job = new Job(documentsToSign, signers, "myReferenceToJob")
{
    AuthenticationLevel = AuthenticationLevel.Four
};

Note

Note that only public organizations can do NotificationsUsingLookup.

Step 2: Get status changes

To find out what the status of the signature jobs you have created, you must periodically send requests to the signature service (polling). As a sender, you need to check to which job the update applies to, update the status in your system and then confirm it.

The response to this call will be one of two things:

  • status update: a 200 OK response that contains information about new status for one job. This is defined by the element portal-signature-job-status-change-response.

  • no update available: If there are no updates to your signature jobs, you will receive a 204 No Content response.

Note

The next allowed polling time will be 10 minutes in the production environment if the queue is empty, while for test environments it will be between 5 and 30 seconds. In practice, the time for the next permitted polling request will be immediate as long as one receives a response that includes a status update.

The following example shows how this can be handled and examples of data to extract from a change response.

Note

Status updates you download will disappear from the queue. This allows you to ask for status updates in parallel, and you will not receive the same status update twice. It is therefore important that you confirm receipt of each status update as soon as possible, because if an error still occurs during transmission or processing, the receipt will be queued again after 10 minutes.

Responses will always include the next permitted poll time, which tells you when you can make the next request, and it is important that this time is met. If you send a request before this time has passed, you will receive a 429 Too Many Requests response. This will also contain a next permitted poll time, containing a new time.

PortalClient portalClient = null; //As initialized earlier

// Repeat the polling until signer signs the document, but ensure to do this at a
// reasonable interval. If you are processing the result a few times a day in your
// system, only poll a few times a day.
var change = await portalClient.GetStatusChange();

switch (change.Status)
{
    case JobStatus.NoChanges:
        //Queue is empty. Additional polling will result in blocking for a defined period.
        break;
    case JobStatus.Failed:
    case JobStatus.InProgress:
    case JobStatus.CompletedSuccessfully:
    {
        var signatureJobStatus = change.Status;
        var signatures = change.Signatures;
        var signatureOne = signatures.ElementAt(0);
        var signatureOneStatus = signatureOne.SignatureStatus;
        break;
    }
}

var pollingWillResultInBlock = change.NextPermittedPollTime > DateTime.Now;
if (pollingWillResultInBlock)
{
    //Wait until next permitted poll time has passed before polling again.
}

//Confirm the receipt to remove it from the queue
await portalClient.Confirm(change.ConfirmationReference);

Step 3: Get signed documents

PortalClient portalClient = null; //As initialized earlier
var jobStatusChanged = await portalClient.GetStatusChange();

//Get PAdES:
var pades = await portalClient.GetPades(jobStatusChanged.PadesReference);

Specifying queues

An important and necessary feature for organizations using more than one application to create signature jobs through the API. It enables an application to retrieve status changes independent of other applications.

The pollingQueue property is used to assign jobs to a specified queue which is then used to retrieve status changes. If your organization is using more than one application/integration to access our API, we strongly recommend using a separate queue for each one. This is to ensure that one does not retrieve the others’ status updates. This may result in missing status updates for jobs in one of the applications, which in turn will result in a poor user experience. Only use the default queue, eg. not specifying a queue, when only one of your applications access our API.

To specify a queue, set pollingQueue through when constructing a Sender. Please note that the same sender must be specified when polling to retrieve status changes. The Sender can be set globally in ClientConfiguration or on every job.

PortalClient portalClient = null; //As initialized earlier

var organizationNumber = "123456789";
var sender = new Sender(organizationNumber, new PollingQueue("CustomPollingQueue"));

var documentsToSign = new List<Document>
{
    new Document(
        "Document title",
        FileType.Pdf,
        @"C:\Path\ToDocument\File.pdf"
    )
};

var signers = new List<Signer>
{
    new Signer(new PersonalIdentificationNumber("00000000000"), new NotificationsUsingLookup())
};

var portalJob = new Job("Job title", documentsToSign, signers, "myReferenceToJob", sender);

var portalJobResponse = await portalClient.Create(portalJob);

var changedJob = await portalClient.GetStatusChange(sender);

Delete documents

After receiving a status change, the documents can be deleted as follows:

This is currently not implemented in the C# client. However all contents of non-completed jobs, as well as completed jobs without Long-term validation and storage will be deleted automatically in 40 days.