Last modified: Oct 5, 2026

Notifications

How to use notifications on instantiation

This document describes sending notification(s) to the instance owner when an instance is created. Here is an overview of the functionality and how you can try it out.

This functionality is available from version 8.11.0 of Altinn.App.Api and Altinn.App.Core.

What’s new?

A new field, notification, has been added to the request body of POST /instances/create and POST /instances (multipart). This field allows you to specify which channel the notification should be sent on, and optionally provide custom texts, a scheduled send time, and reminders.

The notification is ordered after the instance has been created. If ordering it fails, the instance is still created and the error is logged by the app. An invalid notification object rejects the whole request.

How it works

Fields in the notification object

InstantiationNotification

FieldTypeRequiredDescription
notificationChannelint (enum)NoChannel for sending. Default: 4 (EmailAndSms). See table below for valid values.
languagestringNoLanguage code (nb, nn, en). Only used for organizations – individuals use their profile language.
requestedSendTimestring (datetime)NoEarliest time for sending (ISO 8601, UTC). If not set, the notification is sent as soon as possible. Maximum delay is 30 days.
allowSendingAfterWorkHoursboolNoAllows sending outside of working hours. Default: false (daytime only). Only affects SMS, email is sent regardless of time of day.
customSmsobjectNoCustom SMS text and sender name. If not set, default text is used.
customEmailobjectNoCustom email subject and body. If not set, default text is used.
reminderslistNoList of reminders that can be sent after the initial notification.

customSms

FieldTypeRequiredDescription
senderNamestringYesSender name displayed in the SMS. Max 11 characters.
textCustomTextYesCustom SMS text in nb, nn and en.

NOTE: If the sender name senderName is (or in the future will be) protected by a third party product such as SenderID, you must allow Altinn/Digitaliseringsdirektoratet as message producer.

customEmail

FieldTypeRequiredDescription
subjectCustomTextYesCustom subject in nb, nn and en.
bodyCustomTextYesCustom body text in nb, nn and en.

CustomText

FieldTypeRequiredDescription
nbstringYesText in Norwegian Bokmål.
nnstringYesText in Norwegian Nynorsk.
enstringYesText in English.

reminders (list of reminder objects)

Each object in the reminders list may contain the following fields:

FieldTypeRequiredDescription
requestedSendTimestring (datetime)NoEarliest time for sending the reminder (ISO 8601, UTC). Cannot be combined with sendAfterDays. Maximum delay is 30 days.
sendAfterDaysintNoNumber of days after the initial notification before the reminder is sent. Cannot be combined with requestedSendTime. Maximum delay is 30 days.
customSmsobjectNoOverrides the SMS text from the initial notification for this reminder.
customEmailobjectNoOverrides the email text from the initial notification for this reminder.

If neither requestedSendTime nor sendAfterDays is set, the reminder is sent as soon as possible after the initial notification has been processed.

If no custom texts are provided on the reminder, the texts from the initial notification are inherited.

Reminders are cancelled the same way as the initial notification, see Cancelling notifications.

Channel selection (notificationChannel)

Note that notificationChannel is an integer enum, not a string. Valid values are:

ValueChannelDescription
0EmailEmail only
1SmsSMS only
2EmailPreferredEmail first, SMS as fallback if the recipient has no email address
3SmsPreferredSMS first, email as fallback if the recipient has no phone number
4EmailAndSmsBoth email and SMS are sent simultaneously (default)

For self-identified users (instance owner with externalIdentifier), EmailPreferred is always used.

Language

  • For individuals, the language is automatically retrieved from their Altinn profile, with Norwegian Bokmål as fallback.
  • For self-identified users, the language is retrieved from their Altinn profile, with English as fallback.
  • For organizations, the language specified in the instantiation request (language field in the notification object) is used, with Norwegian Bokmål as fallback.

Send time

By default, SMS notifications are only sent during working hours. To allow sending at any time of day, set allowSendingAfterWorkHours to true. Email is sent regardless of time of day.

Scheduled send time

If requestedSendTime is set, the notification will not be sent before that time.

If requestedSendTime is not set, the notification is sent as soon as possible (typically within a few minutes).

Cancelling notifications

Before sending the notification or a reminder, Altinn Notifications uses a send condition to ask the app whether to go ahead. The app says no when the instance has been deleted or, by default, when its process has ended.

Cancelling notifications requires Maskinporten. The app reads the instance with a service owner token, which always asks for both altinn:serviceowner/instances.read and altinn:serviceowner/instances.write, so its Maskinporten client must have both scopes. See the Maskinporten integration guide. Without it, the app can’t read the instance, and every notification and reminder is sent. Ordering notifications works without Maskinporten, so a missing client only shows when a notification that should have been cancelled is sent.

If the app can’t read the instance, for example because of a temporary error, Altinn Notifications tries once more. If that attempt fails too, the notification is sent.

Custom cancellation logic

By default, the notification is only sent while the process has not ended. This is not necessarily when the form is submitted: if the process has more steps after the user is done, the notification can still be sent while those steps run.

You can override this behaviour by implementing the ICancelInstantiationNotification interface and registering it in the DI container. Your implementation is only called for instances that exist and are not deleted:

public class MyNotificationCancellation : ICancelInstantiationNotification
{
    public bool ShouldSend(Instance instance)
    {
        // Custom logic here, example:
        // Only send the notification if the instance is not archived
        return instance.Status?.IsArchived is not true;
    }
}

Register the implementation in Program.cs:

services.AddTransient<ICancelInstantiationNotification, MyNotificationCancellation>();

Default texts

If you do not provide custom texts, default texts will be used. The default SMS text is the same as the body of the default email.

Example of a received email with default text:

Subject: New form created in Altinn

Body: The Norwegian Test Department has created a new form (notification-instantiation-ttd) for ASTROLOG NÆR with social security number 54928201018 - open your Altinn inbox to view the form.

Custom texts and tokens

Custom texts support the following tokens, which are replaced dynamically:

TokenDescription
$appName$The name of the app, from its app ID ({org}/{app})
$instanceOwnerName$The name of the instance owner
$serviceOwnerName$The name of the service owner, as defined in the Altinn CDN
$orgNumber$The organization number of the instance owner, if the instance owner is an organization
$personNumber$The national identity number of the instance owner, if the instance owner is an individual. $socialSecurityNumber$ also works.
$dueDate$The due date of the instance, if set, in Norwegian time (format: dd-MM-yyyy HH:mm:ss)

How are recipient addresses determined?

Altinn Notifications handles this based on Altinn Profile for individuals and the registry for organizations.

In test environments, contact details can be updated for testing at https://tt02.altinn.no/ui/Profile.

For SMS testing in a test environment, the phone number must be whitelisted. Please get in touch if this is needed.

Examples

Each example below is shown for both endpoints:

  • POST /{org}/{app}/instances/create — simplified endpoint. The entire body is a single JSON object.
  • POST /{org}/{app}/instances — multipart endpoint. The notification must be sent as a separate multipart part with name="notification" and Content-Type: application/json. A notification part without Content-Type: application/json, or a notification field inside the instance template part, is silently ignored.

The dates in the examples are only examples. requestedSendTime must be in the future, and at most 30 days ahead.

Simple example of instance creation with notification

    {
      "instanceOwner": {
        "personNumber": "54928201018"
      },
      "notification": {
        "notificationChannel": 0
      }
    }
    
    POST /ttd/my-app/instances HTTP/1.1
    Content-Type: multipart/form-data; boundary=boundary
    
    --boundary
    Content-Disposition: form-data; name="instance"
    Content-Type: application/json
    
    {
      "instanceOwner": {
        "personNumber": "54928201018"
      }
    }
    --boundary
    Content-Disposition: form-data; name="notification"
    Content-Type: application/json
    
    {
      "notificationChannel": 0
    }
    --boundary--
    

    Example with custom texts

      {
        "instanceOwner": {
          "personNumber": "54928201018"
        },
        "notification": {
          "notificationChannel": 4,
          "customSms": {
            "senderName": "MyOrg",
            "text": {
              "nb": "$appName$ er klar for $instanceOwnerName$",
              "nn": "$appName$ er klar for $instanceOwnerName$",
              "en": "$appName$ is ready for $instanceOwnerName$"
            }
          },
          "customEmail": {
            "subject": {
              "nb": "$appName$ - ny instans opprettet",
              "nn": "$appName$ - ny instans oppretta",
              "en": "$appName$ - new instance created"
            },
            "body": {
              "nb": "Hei $instanceOwnerName$, en ny instans av $appName$ er opprettet for deg.",
              "nn": "Hei $instanceOwnerName$, ei ny instans av $appName$ er oppretta for deg.",
              "en": "Hello $instanceOwnerName$, a new instance of $appName$ has been created for you."
            }
          }
        }
      }
      
      POST /ttd/my-app/instances HTTP/1.1
      Content-Type: multipart/form-data; boundary=boundary
      
      --boundary
      Content-Disposition: form-data; name="instance"
      Content-Type: application/json
      
      {
        "instanceOwner": {
          "personNumber": "54928201018"
        }
      }
      --boundary
      Content-Disposition: form-data; name="notification"
      Content-Type: application/json
      
      {
        "notificationChannel": 4,
        "customSms": {
          "senderName": "MyOrg",
          "text": {
            "nb": "$appName$ er klar for $instanceOwnerName$",
            "nn": "$appName$ er klar for $instanceOwnerName$",
            "en": "$appName$ is ready for $instanceOwnerName$"
          }
        },
        "customEmail": {
          "subject": {
            "nb": "$appName$ - ny instans opprettet",
            "nn": "$appName$ - ny instans oppretta",
            "en": "$appName$ - new instance created"
          },
          "body": {
            "nb": "Hei $instanceOwnerName$, en ny instans av $appName$ er opprettet for deg.",
            "nn": "Hei $instanceOwnerName$, ei ny instans av $appName$ er oppretta for deg.",
            "en": "Hello $instanceOwnerName$, a new instance of $appName$ has been created for you."
          }
        }
      }
      --boundary--
      

      Example with scheduled send time and sending outside working hours

        {
          "instanceOwner": {
            "personNumber": "54928201018"
          },
          "notification": {
            "notificationChannel": 1,
            "requestedSendTime": "2025-12-01T09:00:00Z",
            "allowSendingAfterWorkHours": true
          }
        }
        
        POST /ttd/my-app/instances HTTP/1.1
        Content-Type: multipart/form-data; boundary=boundary
        
        --boundary
        Content-Disposition: form-data; name="instance"
        Content-Type: application/json
        
        {
          "instanceOwner": {
            "personNumber": "54928201018"
          }
        }
        --boundary
        Content-Disposition: form-data; name="notification"
        Content-Type: application/json
        
        {
          "notificationChannel": 1,
          "requestedSendTime": "2025-12-01T09:00:00Z",
          "allowSendingAfterWorkHours": true
        }
        --boundary--
        

        Example with reminders

          {
            "instanceOwner": {
              "personNumber": "54928201018"
            },
            "notification": {
              "notificationChannel": 0,
              "requestedSendTime": "2025-12-01T09:00:00Z",
              "reminders": [
                {
                  "sendAfterDays": 7
                },
                {
                  "requestedSendTime": "2025-12-15T12:30:00Z",
                  "customEmail": {
                    "subject": {
                      "nb": "Påminnelse: $appName$ venter på deg",
                      "nn": "Påminning: $appName$ ventar på deg",
                      "en": "Reminder: $appName$ is waiting for you"
                    },
                    "body": {
                      "nb": "Hei $instanceOwnerName$, vi minner om at $appName$ fortsatt venter på svar.",
                      "nn": "Hei $instanceOwnerName$, vi minner om at $appName$ framleis ventar på svar.",
                      "en": "Hello $instanceOwnerName$, we would like to remind you that $appName$ is still awaiting your response."
                    }
                  }
                }
              ]
            }
          }
          
          POST /ttd/my-app/instances HTTP/1.1
          Content-Type: multipart/form-data; boundary=boundary
          
          --boundary
          Content-Disposition: form-data; name="instance"
          Content-Type: application/json
          
          {
            "instanceOwner": {
              "personNumber": "54928201018"
            }
          }
          --boundary
          Content-Disposition: form-data; name="notification"
          Content-Type: application/json
          
          {
            "notificationChannel": 0,
            "requestedSendTime": "2025-12-01T09:00:00Z",
            "reminders": [
              {
                "sendAfterDays": 7
              },
              {
                "requestedSendTime": "2025-12-15T12:30:00Z",
                "customEmail": {
                  "subject": {
                    "nb": "Påminnelse: $appName$ venter på deg",
                    "nn": "Påminning: $appName$ ventar på deg",
                    "en": "Reminder: $appName$ is waiting for you"
                  },
                  "body": {
                    "nb": "Hei $instanceOwnerName$, vi minner om at $appName$ fortsatt venter på svar.",
                    "nn": "Hei $instanceOwnerName$, vi minner om at $appName$ framleis ventar på svar.",
                    "en": "Hello $instanceOwnerName$, we would like to remind you that $appName$ is still awaiting your response."
                  }
                }
              }
            ]
          }
          --boundary--
          

          Self-identified users

          ID-porten email user

            {
              "instanceOwner": {
                "externalIdentifier": "urn:altinn:person:idporten-email:jens.jensen@digdir.no"
              },
              "notification": {
                "notificationChannel": 0
              }
            }
            
            POST /ttd/my-app/instances HTTP/1.1
            Content-Type: multipart/form-data; boundary=boundary
            
            --boundary
            Content-Disposition: form-data; name="instance"
            Content-Type: application/json
            
            {
              "instanceOwner": {
                "externalIdentifier": "urn:altinn:person:idporten-email:jens.jensen@digdir.no"
              }
            }
            --boundary
            Content-Disposition: form-data; name="notification"
            Content-Type: application/json
            
            {
              "notificationChannel": 0
            }
            --boundary--
            

            Legacy username and password

              {
                "instanceOwner": {
                  "externalIdentifier": "urn:altinn:person:legacy-selfidentified:jensjensen"
                },
                "notification": {
                  "notificationChannel": 0
                }
              }
              
              POST /ttd/my-app/instances HTTP/1.1
              Content-Type: multipart/form-data; boundary=boundary
              
              --boundary
              Content-Disposition: form-data; name="instance"
              Content-Type: application/json
              
              {
                "instanceOwner": {
                  "externalIdentifier": "urn:altinn:person:legacy-selfidentified:jensjensen"
                }
              }
              --boundary
              Content-Disposition: form-data; name="notification"
              Content-Type: application/json
              
              {
                "notificationChannel": 0
              }
              --boundary--