📨 Unified Messaging API

Send SMS and Email messages with built-in throttling and simulation mode

Version 1.0.0

Unified Messaging API Documentation

Version: 1.0.0
Base URL: https://apiaccess.digify.no/api/v1


🤖 Building an API client with AI?

Get the comprehensive Client Development Guide - optimized for Claude Code and other AI tools. Includes TypeScript types, example implementations in multiple languages, and best practices.

- View online: https://apiaccess.digify.no/client-guide
- Download markdown: https://apiaccess.digify.no/client-guide?format=md


#Authentication

All API endpoints (except health checks) require an AccessToken for authentication.

Methods to provide AccessToken:
1. Query parameter: ?AccessToken=YOUR_TOKEN
2. Header: X-Access-Token: YOUR_TOKEN
3. Header: Authorization: Bearer YOUR_TOKEN

Test Token: Contact administrator for access token


#Endpoints

#1. Send Messages

Send SMS and/or Email messages.

Endpoint: POST /api/v1/messages/send

Authentication: Required

Request Body:

{
"messages": [
{
"type": "sms",
"id": "optional-client-id",
"sourceAddr": "1234",
"destAddr": "4712345678",
"msg": "Hello from Unified Messaging API!",
"priority": 0,
"dataCoding": 1
},
{
"type": "email",
"sourceAddr": "noreply@example.com",
"sourceAddrName": "Example Service",
"destAddr": "user@example.com",
"subject": "Welcome",
"body": "<html><body><h1>Welcome!</h1></body></html>",
"bodyFormat": "html"
}
]
}

#### SMS Message Fields

FieldTypeRequiredDescription
typestringYesMust be "sms"
idstringNoClient-provided message ID
sourceAddrstringNoSender address (max 15 chars)
sourceAddrTonnumberNoSource address TON (0-255)
sourceAddrNpinumberNoSource address NPI (0-255)
destAddrstringYesRecipient phone number (max 15 chars)
msgstringYesMessage content (max 1600 chars)
esmClassnumberNoESM class (0-255)
protocolIdnumberNoProtocol ID (0-255)
prioritynumberNoPriority (0-255)
sendWhenstring/dateNoScheduled send time
scheduleDeliveryTimestring/dateNoSchedule delivery time
validityPeriodstring/dateNoValidity period
dataCodingnumberNoData coding (0-255)

#### Email Message Fields
FieldTypeRequiredDescription
typestringYesMust be "email"
sourceAddrstringYesSender email address
sourceAddrNamestringNoSender name (max 200 chars)
destAddrstringYesRecipient email address
destAddrNamestringNoRecipient name (max 200 chars)
subjectstringYesEmail subject (max 500 chars)
bodystringYesEmail body (max 1MB)
bodyFormatstringNo"html" or "text" (default: "html")
emailProviderIdnumberNoEmail provider ID (default: 2)

#### Success Response (200 OK)

{
"status": "success",
"simulationMode": false,
"results": [
{
"id": "optional-client-id",
"type": "sms",
"status": "queued",
"messageId": 123456,
"msgCount": 1
},
{
"type": "email",
"status": "queued",
"emailId": 789
}
],
"summary": {
"total": 2,
"sms": 1,
"email": 1,
"creditsUsed": 1
}
}

#### Error Responses

Authentication Error (401)

{
"status": "error",
"error": {
"code": "AUTHENTICATION_FAILED",
"message": "Invalid AccessToken"
}
}

Validation Error (400)

{
"status": "error",
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request data",
"details": [...]
}
}

Rate Limit Error (429)

{
"status": "error",
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded for SMS. Limit: 6. Current: 6. Try again in 7 seconds.",
"retryAfter": 7,
"details": {
"messageType": "SMS",
"limit": 6,
"currentCount": 6
}
}
}

Note: Rate limit responses include a Retry-After header.

Insufficient Credit Error (402)

{
"status": "error",
"error": {
"code": "INSUFFICIENT_CREDIT",
"message": "Insufficient SMS credits. Required: 5, Available: 2",
"details": {
"creditsNeeded": 5,
"creditsAvailable": 2
}
}
}


#2. Health Check

Check if the API service is healthy.

Endpoint: GET /health

Authentication: Not required

Response (200 OK):

{
"status": "healthy",
"timestamp": "2025-10-18T12:00:00.000Z",
"environment": "development",
"database": "connected"
}

Response (503 Service Unavailable):

{
"status": "unhealthy",
"timestamp": "2025-10-18T12:00:00.000Z",
"environment": "development",
"database": "disconnected",
"error": "Connection timeout"
}


#3. Readiness Check

Check if the API service is ready to accept requests.

Endpoint: GET /ready

Authentication: Not required

Response (200 OK):

{
"status": "ready",
"timestamp": "2025-10-18T12:00:00.000Z"
}


#4. Get SMS Logs

Retrieve SMS message logs for your system.

Endpoint: GET /api/v1/logs/sms

Authentication: Required

Query Parameters:

ParameterTypeRequiredDescription
limitnumberNoNumber of records to return (1-100, default: 50)
offsetnumberNoNumber of records to skip (default: 0)
statusstringNoFilter by message status
startDatestringNoFilter by start date (ISO 8601 format)
endDatestringNoFilter by end date (ISO 8601 format)

Success Response (200 OK):
{
"status": "success",
"data": [
{
"messageId": 10798634,
"destAddr": "4791748750",
"msg": "Test SMS from production API",
"msgCount": 1,
"status": "queued",
"createdAt": "2025-10-18T11:34:15.000Z",
"sendWhen": "2025-10-18T11:34:15.000Z",
"sourceAddr": "1234567890"
}
],
"pagination": {
"total": 150,
"limit": 50,
"offset": 0,
"hasMore": true
}
}


#5. Search Companies

Search for Norwegian companies by name or organization number.

Endpoint: GET /api/v1/companies/search

Authentication: Required

Query Parameters:

ParameterTypeRequiredDescription
searchstringYesCompany name or 9-digit organization number

Success Response (200 OK):
{
"status": "success",
"companies": [
{
"orgNr": "987654321",
"navn": "Example Company AS",
"forrAdrPostSted": "Oslo"
},
{
"orgNr": "123456789",
"navn": "Another Example AS",
"forrAdrPostSted": "Bergen"
}
]
}

Notes:
- If search is exactly 9 numeric digits, searches by organization number
- Otherwise, searches by company name (prefix match)
- Returns maximum 5 results
- Excludes hidden and deleted companies from name searches


#6. Get Company by Organization Number

Get a specific company by its organization number.

Endpoint: GET /api/v1/companies/:orgNr

Authentication: Required

URL Parameters:

ParameterTypeRequiredDescription
orgNrstringYes9-digit organization number

Success Response (200 OK):

Returns comprehensive company information with all available fields:

{
"status": "success",
"companies": [
{
"orgnr": 984851006,
"navn": "DNB BANK ASA",
"organisasjonsform": "ASA",
"forretningsadr": "Dronning Eufemias gate 30",
"forradrpostnr": "0191",
"forradrpoststed": "OSLO",
"forradrkommnr": 301,
"forradrkommnavn": "OSLO",
"forradrland": "Norge",
"postadresse": "Postboks 1600 Sentrum",
"ppostnr": "0021",
"ppoststed": "OSLO",
"ppostland": "Norge",
"regifr": true,
"regimva": true,
"nkode1": "64.190",
"nkode2": null,
"nkode3": null,
"sektorkode": 3200,
"konkurs": false,
"avvikling": false,
"tvangsavvikling": false,
"regiaa": false,
"regifriv": false,
"regdato": "2002-09-12T00:00:00.000Z",
"stiftelsesdato": "2002-09-10T00:00:00.000Z",
"tlf": null,
"tlf_mobil": "4791504800",
"url": "www.dnb.no",
"regnskap": 2023,
"hovedenhet": null,
"ansatte_antall": 8343,
"ansatte_dato": "2025-02-12T00:00:00.000Z",
"Slettet": false,
"Hidden": false
}
]
}

Field Descriptions:

FieldTypeDescription
orgnrnumberOrganization number
navnstringCompany name
organisasjonsformstringOrganization form (AS, ASA, etc.)
forretningsadrstringBusiness address street
forradrpostnrstringBusiness address postal code
forradrpoststedstringBusiness address city
forradrkommnrnumberBusiness address municipality number
forradrkommnavnstringBusiness address municipality name
forradrlandstringBusiness address country
postadressestringPostal address
ppostnrstringPostal code
ppoststedstringPostal city
ppostlandstringPostal country
regifrbooleanRegistered in Foretaksregisteret
regimvabooleanRegistered for VAT
nkode1stringPrimary industry code (NACE)
nkode2stringSecondary industry code
nkode3stringTertiary industry code
sektorkodenumberSector code
konkursbooleanIn bankruptcy
avviklingbooleanIn liquidation
tvangsavviklingbooleanIn forced liquidation
regiaabooleanRegistered in Employer Register
regifrivbooleanRegistered for voluntary organizations
regdatostringRegistration date (ISO 8601)
stiftelsesdatostringFoundation date (ISO 8601)
tlfstringPhone number
tlf_mobilstringMobile phone
urlstringWebsite URL
regnskapnumberLatest accounting year
hovedenhetnumberParent organization number
ansatte_antallnumberNumber of employees
ansatte_datostringEmployee count date (ISO 8601)
SlettetbooleanDeleted status
HiddenbooleanHidden status

Error Response (400 Bad Request):
{
"status": "error",
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid organization number",
"details": [
{
"code": "invalid_string",
"message": "Organization number must be exactly 9 digits",
"path": ["orgNr"]
}
]
}
}


#7. Get Email Logs

Retrieve Email message logs for your system.

Endpoint: GET /api/v1/logs/email

Authentication: Required

Query Parameters:

ParameterTypeRequiredDescription
limitnumberNoNumber of records to return (1-100, default: 50)
offsetnumberNoNumber of records to skip (default: 0)
statusstringNoFilter by message status
startDatestringNoFilter by start date (ISO 8601 format)
endDatestringNoFilter by end date (ISO 8601 format)

Success Response (200 OK):
{
"status": "success",
"data": [
{
"emailId": 549870,
"sourceAddr": "noreply@sqlexpert.no",
"destAddr": "nilsarne@tvedten.no",
"subject": "Test from Production API",
"status": "queued",
"createdAt": "2025-10-18T11:34:18.000Z",
"bodyFormat": "html"
}
],
"pagination": {
"total": 75,
"limit": 50,
"offset": 0,
"hasMore": true
}
}


#Features

#Simulation Mode

When a system is configured with SimulationMode = 1, all messages are stored in simulation tables instead of being sent. This is perfect for testing and development.

To enable simulation mode:

UPDATE CloudCustomer.dbo.APIAccess
SET SimulationMode = 1, Environment = 'Development'
WHERE AccessToken = 'YOUR_ACCESS_TOKEN';

Response in simulation mode:

{
"status": "success",
"simulationMode": true,
"results": [
{
"type": "sms",
"status": "simulated",
"messageId": 1,
"msgCount": 1
}
],
"summary": {
"total": 1,
"sms": 1,
"email": 0,
"creditsUsed": 0
}
}

#Throttling

The API enforces rate limits based on the system's environment (Development/Production).

Default limits:

EnvironmentTypePer MinutePer HourPer Day
DevelopmentSMS660500
DevelopmentEmail605005,000
ProductionSMS603,00050,000
ProductionEmail30010,000100,000

To customize limits for a specific system:
INSERT INTO CloudCustomer.dbo.MessageThrottleConfig
(SystemID, MessageType, Environment, MaxPerMinute, MaxPerHour, MaxPerDay, Enabled)
VALUES
(123, 'SMS', 'Development', 10, 100, 1000, 1);


#cURL Examples

#Send SMS (Production)


curl -X POST https://apiaccess.digify.no/api/v1/messages/send?AccessToken=YOUR_ACCESS_TOKEN \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"type": "sms",
"destAddr": "4712345678",
"msg": "Hello from API!"
}
]
}'

#Send Email


curl -X POST https://apiaccess.digify.no/api/v1/messages/send?AccessToken=YOUR_ACCESS_TOKEN \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"type": "email",
"sourceAddr": "noreply@example.com",
"destAddr": "user@example.com",
"subject": "Test Email",
"body": "<h1>Hello!</h1>"
}
]
}'

#Send Both SMS and Email


curl -X POST https://apiaccess.digify.no/api/v1/messages/send?AccessToken=YOUR_ACCESS_TOKEN \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"type": "sms",
"destAddr": "4712345678",
"msg": "Hello via SMS!"
},
{
"type": "email",
"sourceAddr": "noreply@example.com",
"destAddr": "user@example.com",
"subject": "Hello",
"body": "Hello via Email!"
}
]
}'

#Get SMS Logs


# Get latest 50 SMS messages
curl https://apiaccess.digify.no/api/v1/logs/sms?AccessToken=YOUR_ACCESS_TOKEN

Get 10 SMS messages with pagination


curl https://apiaccess.digify.no/api/v1/logs/sms?AccessToken=YOUR_ACCESS_TOKEN&limit=10&offset=0

Filter by date range


curl "https://apiaccess.digify.no/api/v1/logs/sms?AccessToken=YOUR_ACCESS_TOKEN&startDate=2025-10-01&endDate=2025-10-18"

#Get Email Logs


# Get latest 50 email messages
curl https://apiaccess.digify.no/api/v1/logs/email?AccessToken=YOUR_ACCESS_TOKEN

Get 10 email messages with pagination


curl https://apiaccess.digify.no/api/v1/logs/email?AccessToken=YOUR_ACCESS_TOKEN&limit=10&offset=0

Filter by date range


curl "https://apiaccess.digify.no/api/v1/logs/email?AccessToken=YOUR_ACCESS_TOKEN&startDate=2025-10-01&endDate=2025-10-18"

#Search Companies


# Search by company name
curl "https://apiaccess.digify.no/api/v1/companies/search?search=Acme&AccessToken=YOUR_ACCESS_TOKEN"

Search by organization number (9 digits)


curl "https://apiaccess.digify.no/api/v1/companies/search?search=987654321&AccessToken=YOUR_ACCESS_TOKEN"

#Get Company by Organization Number


curl https://apiaccess.digify.no/api/v1/companies/987654321?AccessToken=YOUR_ACCESS_TOKEN

#Health Check


curl https://apiaccess.digify.no/health


#Error Codes


CodeHTTP StatusDescription
AUTHENTICATION_FAILED401Invalid or missing AccessToken
VALIDATION_ERROR400Invalid request data
RATE_LIMIT_EXCEEDED429Too many requests
INSUFFICIENT_CREDIT402Not enough SMS credits
DATABASE_ERROR500Database operation failed
INTERNAL_SERVER_ERROR500Unexpected server error
NOT_FOUND404Endpoint not found


#Rate Limit Headers

When rate limiting is triggered, the response includes:
- Retry-After: Number of seconds to wait before retrying


#Best Practices

1. Batch Messages: Send multiple messages in one request to reduce overhead
2. Handle Rate Limits: Implement exponential backoff when receiving 429 responses
3. Use Simulation Mode: Test your integration in simulation mode first
4. Monitor Credits: Check credit balance regularly to avoid 402 errors
5. Error Handling: Always check the status field in responses


#Support

For issues or questions:
- Check logs at ./logs/messaging-api.log
- Review database tables: MessageThrottleLog, MessagingAPILog
- Contact support with your SystemID for assistance