Welcome to the 46elks API!

You can send and receive SMS, handle incoming phone calls, make automatic phone calls, allocate phone numbers and more.

Create an account to get started. Once you have an account you can find your API username and password in the dashboard.

Every request should be authenticated using basic auth. Read this introduction to basic auth if you haven’t used it before.

Parameters are sent as urlencoded POST-variables and the base URL for all request is: https://api.46elks.com/a1/

All API-responses are in JSON format.

You will receive a 403 Forbidden or 404 Not found response in case of an error. Details are sent as plain text in the HTTP content.

Table of contents




Voice calls

Phone numbers


Account & subaccounts

SMS messages

Sending SMS

To send a new SMS simply POST to the /SMS resource. The “from” number can either be one of your previously allocated mobile phone numbers or an alphanumeric string.

POST https://api.46elks.com/a1/SMS

Key Value
from +46766861004 or "HelloWorld"
to +46704508449
message Don't forget the doctor at 08:35 tomorrow!

curl Elixir Java PHP Python Ruby

curl -X POST \
  -u <API Username>:<API Password> \
  -d "from=CurlyElk" \
  -d "message=Bring a sweater, it’s cold outside!" \
  -d "to=+46766861004" \
import HTTPotion.base

authdata = [basic_auth: {'<API-Username>',

request = %{
            "from"    => "ElixirElk",
            "to"      => "+46766861004",
            "message" => "Bring a sweater, it’s cold outside!"

request_data = URI.encode_query(request)

  [body: request_data , ibrowse: authdata]
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

public class UnirestSendSMS {
  public static void main(String[] args) {
    try {
      System.out.println("Sending SMS");

      HttpResponse<String> response = Unirest.post("https://api.46elks.com/a1/SMS")
        .basicAuth("<API Username>","<API Password>")
        .field("to", "+46766861004")
        .field("from", "JavaElk")
        .field("message", "Bring a sweater, it’s cold outside!")


    catch (Exception e){
function sendSMS ($sms) {
  $username = "USERNAME";
  $password = "PASSWORD";
  $context = stream_context_create(array(
    'http' => array(
      'method' => 'POST',
      'header'  => 'Authorization: Basic '.
                   base64_encode($username.':'.$password). "\r\n".
                   "Content-type: application/x-www-form-urlencoded\r\n",
      'content' => http_build_query($sms),
      'timeout' => 10
  $response = file_get_contents("https://api.46elks.com/a1/SMS",
    false, $context);

  if (!strstr($http_response_header[0],"200 OK"))
    return $http_response_header[0];
  return $response;
$sms = array(
  "from" => "PHPElk",   /* Can be up to 11 alphanumeric characters */
  "to" => "+46766861004",  /* The mobile number you want to send to */
  "message" => "Bring a sweater, it’s cold outside!",
echo sendSMS($sms);
import requests

auth = (
    '<API Username>',
    '<API Password>'

fields = {
    'from': 'PythonElk',
    'to': '+46723175800',
    'message': 'Test Message To your phone.'

response = requests.post(

require 'net/http'

uri = URI('https://api.46elks.com/a1/SMS')
req = Net::HTTP::Post.new(uri)
req.basic_auth '<API Username>', '<API Password>'
  :from => 'RubyElk',
  :to => '+46704508449',
  :message => 'Login code 123456'

res = Net::HTTP.start(
    :use_ssl => uri.scheme == 'https') do |http|
  http.request req

puts res.body

When using an alphanumeric “from” it needs to be between 3-11 characters in length and you are restricted to using only a-z, A-Z, 0-9. No other characters can be used, and the name has to begin with a letter. Upon request, we can also unlock other “from” numbers for your account.

More examples
C - C# - Erlang - Go - Google App Script - Haskell - Node.js - Postman

Message texts and costs

SMS messages should always be sent to the API as URL-encoded UTF-8. The maximum text size of a single message is 160 characters. If your message contains characters not available in the GSM 03.38 basic character set it will be encoded as UTF16-BE which as a general rule means up to 70 characters in a single SMS message.

Longer and more expensive SMS messages can be sent. For messages within GSM 03.38 basic, the calculation is N * 153 where N is the number of SMS parts required. For UTF16-BE, the calculation is N * 67 - however, less for code points above 65535.

Splitting and joining multi-part SMS messages are automatically handled by the API. When your message is being split, your account will be charged for each SMS part.

Receiving SMS

Whenever there is an incoming SMS to one of your allocated 46elks numbers we will make a request to your chosen “sms_url” with the following POST-variables:

POST http://myservice.se/callback/newsms.php

Key Value
from +46704508449
to +46766861004
message I want to buy 2 cartons of milk!

Callbacks for incoming SMS will be retried for up to 24 hours until a HTTP 200 OK response is received. The HTTP responses 201 through 204 are also supported.

Replying to a received SMS

If you want to reply to an incoming SMS, just send your reply as text in the HTTP response when your “sms_url” is being requested and it will be sent back to the originating mobile phone.

Thank you for your order.

If there is no text in the response or if HTTP 204 No Content response is received no message will be sent back to the originating mobile phone.

Flash SMS

Sometimes you want to show a message directly to the mobile phone user. In a more alerted way and without storing it. We call this cellphone feature Flash SMS. You can send these with 46elks by setting the POST variable “flashsms” to “yes” when sending SMS.

This is what a Flash SMS looks like on an iPhone:

Delivery reports

Optional delivery reports allow you to track SMS messages you send and find out if they have reached the destination. To activate delivery reports simply add your callback URL to the POST variable “whendelivered” when you send an SMS.

Whenever we have new delivery information regarding your SMS, we will make a POST request to your URL with the following:

POST http://myservice.se/callback/dlr.php

Key Value
id The SMS id returned from POST to /SMS
status Either "sent", "delivered" or "failed"
delivered Time of delivery (only for status=delivered)

Callbacks for Delivery Reports will be retried for up to 24 hours until a HTTP 200 OK response is received. The HTTP responses 201 through 204 are also supported.

Some destinations and mobile networks does not support delivery reports. Thus, the status of SMS messages you send to such destinations will be “sent”. If the operator supports delivey reports, a message status can then change from sent to delivered or from sent to failed.

MMS messages

When you want to send a picture with your message, you send an mms.

Sending MMS

Send text messages with images.

Key Value
from Your mms-enabled 46elks-number (ex +46766861004) or noreply
to +46704508449
image URL to an image, or a Base64/url-encoded image
message If you wish to also include text together with the image

MMS enabled numbers

Not every number has support for MMS, be sure to look for the “mms” element in the “capabilites” array for your number with GET https://api.46elks.com/a1/Numbers to see if the number you’re trying to use has MMS support enabled.

These numbers currently need to be ordered manually.

Receiving MMS

When there’s an incoming MMS message to one of your numbers a request will be made to the URL as defined by “mms_url” with the following POST-variables:

POST http://myservice.se/callback/newmms.php

Key Value
from +46704508449
to +46766861004
message Hello, world. This is an MMS.
image https://api.46elks.com/a1/images/i7fffc26a7d681205d90b278d86e184b0.jpg

The image contains a link the received JPG or PNG image. If there’s multiple images in a single MMS you’ll find them in image, image2, image3, …, imageN.

Callbacks for incoming MMS will be retried for up to 24 hours until a HTTP 200 OK response is received. The HTTP responses 201 through 204 are also supported.

Voice calls

Incoming calls

Incoming calls are controlled by the “voice_start” attribute on your phone number. The URL you put there will be requested every time there is a new incoming call.

If your “voice_start” contains a JSON object, that action will be triggered directly when incoming calls are received, without making any requests to your web server.

Voice actions

A phone call in 46elks is basically a set of actions and results. Each action is a JSON object explaining what you want to do. And by reading the results you control the flow of actions and ultimately reach the end of the call.



If you use the above JSON as voice_start for an incoming call, it will connect the call to the swedish cell phone number 070-450 84 49 and upon answer allow the two callers to speak to each other.

Actions: Connect - Play a sound - Voice response (IVR) - Hangup - Record

Action chaining

To make something happen after an action is finished or when an action has a certain result, there are specific JSON keys you can define. Each action has it’s own possible results, but most actions have the “next” result key, which indicate “continue here regardless of result”.

Values for result keys can either be a new action object, or a URL string telling 46elks where to fetch action(s) from. URLs are retrieved with HTTP POST.


POST variables

The following variables are always included in the requests to your URLs. For completed actions, the variable “result” is also included.

Key Value
direction incoming
from E.164 caller ID or empty if hidden
to E.164 of the called 46elks number
callid Unique ID for this call

Action - "connect"

Connect the call to a given number, and in the case of an answer, let the two callers speak to each other. The callerid indicates who is calling. You can set it to one of your 46elks numbers. If you leave it out, it will default to the incoming caller’s number.

Key Value
connect E.164 destination number
callerid Either one of your 46elks numbers, or the callling number

Possible results:

Key Value
busy Destination phone number is busy
success Call was answered and the destination phone has ended the call.
failed Destination phone didn't answer or couldn't be reached.
next Continue here regardless. If URL, result will include any of above.

Calls to mobile 46elks numbers can only "connect" to same-country mobile numbers.

Action - "play"

Play an audio file. Could be either a URL on your server or a sound resource provided by 46elks. URLs are fetched using HTTP GET and are always cached, so for unique resources be sure to provide unique URLs.

Supported file formats are WAV, MP3 and OGG Vorbis.

  "play": "http://myserver.se/welcome.wav",
  "next": {
    "connect": "+46704508449",
    "busy": {
      "connect": "+46731704032"

For a successful “play” action, the result will be “next”. In case the resource or URL fails to load, the action result will be “failed”.

If a digit is pressed during “play” or if the audio playback has been completed, the call continues at “next”. You can force the full audio file to be played by setting the option “skippable” to false.

Sound resources and DTMF

Some builtin sound resources are provided by 46elks, such as beeps and DTMF tones. These are:

  • sound/beep
  • sound/dtmf/123 (or any DTMF digit sequence, up to 30 digits)

If you need to add some pause between DTMF tones, use p for one or more short 50ms pauses or the capital letter P for longer 500ms pauses.

There are also sound resources specific to a certain call. This is currently limited to recordings (read below), and all those resources are prefixed with “local”, such as “local/recording1”.

Action - "ivr"

The “ivr” action fills the purpose of playing a sound resource, while also retrieving digits punched by the caller. If no digits are retrieved after playback + 10 seconds of wait, the sound resource will be repeated up to 3 times.

You can change the repeat count using the “repeat” key. You can limit how many seconds to wait for input with the “timeout” key.

By default, the action is completed directly when a single digit has been received.

  "ivr": "http://myserver.se/menu.wav",
  "1": {
    "play": "http://myserver.se/one-was-pressed.wav"
  "2": "http://myserver.se/reply-with-json",
  "3": {
    "play": "http://myserver.se/third-option-selected.wav"

Can I receive the pressed digit?

Yes, when we make a request to your server selected option will be available in the “result” POST variable.

Key Value
result 2

Can I use multiple digits?

If you want to allow input of more digits, use the “digits” key. Yes, instead of coding the options within the JSON you can instruct the 46elks platform to pass the pressed digits to your script, regardless of what the caller pressed. Simply set the key “next” to your URL.

  "ivr": "http://myserver.se/enterpin.wav",
  "digits": 5,
  "next": "http://myserver.se/login.php"

You will get the digits pressed in the “result” POST variable.

Key Value
result 12345

If the users presses fewer digits than set, after 10 seconds, or whatever value you’ve chosen in “timeout” the initial sound resource will be repeated again. You can also tell the user, in the recording, that the user can end input with #. In the following sample, if the user presses 3 digits and then #, the call will then move on to next, and you’ll have access to the 3 digit pin.

  "ivr": "http://myserver.se/enterpin.wav",
  "digits": 6,
  "timeout": 14,
  "next": "http://myserver.se/login.php"

Action - "record"

Record the voice of the caller with this action. Useful for building your own voicemail. By default, recording stops after 3 seconds of silence or when 2 minutes of voice has been recorded.

Control the timelimit by adding an integer to the key “timelimit”. Specified in seconds.

The recording can be saved either directly to a URL of your choice, or stored in the platform locally to allow playback before saving the recording. Set “record” to “local/recording1” if you want to allow playback within the same call. All local recordings are discarded when the call ends.

  "play": "http://myserver.se/entervoicemail.wav",
  "next": {
    "record": "http://myserver.se/newvoicemail.php"

POST http://myserver.se/newvoicemail.php

Key Value
created When the recording was stored
duration Audio length in seconds
wav URL where you can request the WAV audio
callid Source callid for this recording
direction Direction of the call
from E.164 caller id
to E.164 destination of the call

Action - "hangup"

End the call. If this is your first action, it is possible to control signalling, otherwise only "reject" is allowed.

Key Value
hangup "busy" or "reject" or "404"

When does an incoming call end?

Either when your action chain is empty, or when the caller has hangup. Execution of the action chain will not continue in the case of caller hangup, simply because then there is no longer any call to control.

Outgoing calls

To create an outgoing call, simply POST to the /Calls resource. This will instruct 46elks to automatically call the number you have selected. When the dialed number answers, the call will continue according to the “voice_start” argument of the POST.

POST https://api.46elks.com/a1/Calls

Key Value
from One of your 46elks numbers
to The number you want to call, like +46704508449
voice_start URL or JSON of actions to execute
whenhangup URL you want 46elks to POST when call hangup or failed

How can I track unanswered outgoing calls?

Use the “whenhangup” variable if you want to be able to track calls which are never answered, such as busy or failed outgoing calls. This URL will be POST-requested when the call is hangup, either by failure to connect or after a connected call was finished and hangup.

Recording phone calls

With 46elks, you can record the full contents of both incoming and outgoing calls.

Option - “record call”

At any level within your tree of voice actions, you can put the key “record call”. When reaching that depth in your JSON tree, the call will start to be recorded.

  "play": "http://myserver.se/connecting.wav",
  "next": {
    "connect": "+46704508449",
    "recordcall": "http://myserver.se/newrecording.php"

The value for your “record call” should be a URL, and this URL will be POSTed when the call has ended and the recording is done (much like how action “record” works).

Callbacks for Recordings will be retried for up to 24 hours until a HTTP 200 OK response is received. The HTTP responses 201 through 204 are also supported.

Phone numbers

For anything other than just sending SMS, you need one or more 46elks phone numbers. You can either allocate phone numbers manually within the dashbord or using the API.

Number allocation

To allocate a new 46elks phone number make a POST request to the resource /Numbers. The variable “country” is mandatory, while other variables are optional.

POST https://api.46elks.com/a1/Numbers

Key Value
country se
sms_url http://myservice.se/callback/newsms.php
mms_url http://myservice.se/callback/newmms.php
voice_start http://myservice.se/callback/newcall.php

The response when allocating a new number looks like below, and is exactly the same as when you query a number previously allocated:

GET https://api.46elks.com/a1/Numbers/n57c8f48af76bf986a14f251b35389e8b

  "id": "n57c8f48af76bf986a14f251b35389e8b",
  "active": "yes",
  "country": "se",
  "number": "+46766861001",
  "capabilities": [ "sms", "voice", "mms" ],
  "sms&#95;url": "http://myservice.se/callback/newsms.php",
  "mms&#95;url": "http://myservice.se/callback/newmms.php",
  "voice_start": "http://myservice.se/callback/newcall.php"

Modification and deallocation

For incoming SMS messages, the attribute “sms_url” on your numbers is used. And for incoming Voice calls, “voice_start” it what you are looking for. If you ever need to change these, either do it manually in the dashboard or use the API and simply do a POST like this:

POST https://api.46elks.com/a1/Numbers/n57c8f48af76bf986a14f251b35389e8b

Key Value
sms_url http://myservice.se/callback/newsms2.php
voice_start http://myservice.se/callback/newcall2.php

You can also deallocate one of your numbers by setting “active” to “no”. Beware that there is no way to get your number back once it has been deallocated.

46elks credits will be consumed at time of allocation and each new month until deallocated.

SMS & calls history

You can list the SMS messages you have sent and recevied with a simple GET to /SMS. The same can be done for calls, by accessing the /Calls resource.

SMS history

By default you get the 100 latest items.

GET https://api.46elks.com/a1/SMS

  "data": [
      "id": "s17a6dafb12d6b1cabc053d57dac2b9d8",
      "created": "2012-03-14T09:52:07.302000",
      "direction": "outgoing",
      "from": "MyService",
      "to": "+46704508449",
      "message": "Hello hello",
      "status": "delivered",
      "delivered": "2012-03-14T09:52:10Z",
      "cost": 3500
      "id": "s299b2d2a467945f59e1c9ea431eed9d8",
      "created": "2012-03-14T08:44:34.608000",
      "direction": "outgoing-reply",
      "from": "+46766861069",
      "to": "+46704508449",
      "message": "We are open until 19:00 today. Welcome!",
      "status": "delivered",
      "delivered": "2012-03-14T08:44:36Z",
      "cost": 3500
      "id": "s292d2a459e967945fb1c9ea431eed9d8",
      "created": "2012-03-14T08:44:34.135000",
      "direction": "incoming",
      "from": "+46704508449",
      "to": "+46766861069",
      "message": "Hours?",
      "cost": 3500
  "next": "2012-02-21T14:15:30.427000"

The response is in JSON format. The key “data” contains a list of the items you requested.

Get details for one SMS

GET https://api.46elks.com/a1/SMS/s1444681a1210bbda24afc0834

  "created": "2012-03-14T09:52:07.302000",
  "direction": "outgoing",
  "from": "MyService",
  "to": "+46704508449",
  "message": "Hello hello",
  "status": "delivered",
  "delivered": "2012-03-14T09:52:10Z",
  "id": "s1444681a1210063b12f4bda24afc0834",
  "cost": 3500

There is also a key named “next”, which can be used to older history. Do this by adding a “start” argument to your GET request, set to the value of your last “next”.

GET https://api.46elks.com/a1/SMS?start=2012-02-21T14:15:30.42700

  "data": [
      "id": "s053d57dac2b9d894a6dafb12d6b1ca12",
      "created": "2012-02-21T14:15:30.427000",
      "direction": "outgoing",
      "from": "TestElk",
      "to": "+46704508449",
      "message": "One two three testing",
      "status": "delivered",
      "delivered": "2012-02-21T14:15:34Z",
      "cost": 3500

This way you can fetch your full SMS & Calls history if needed.

Calls history

The Calls history works the same way as the SMS history.

GET https://api.46elks.com/a1/Calls

  "data": [
      "direction": "incoming",
      "from": "+46784325653",
      "to": "+46766861388",
      "created": "2016-02-28T23:54:24.469000",
      "actions": [
          "play": "http://www.hack46.com/test.mp3",
          "result": "ok"
          "record": "http://zapier.com/hooks/catch/opi0ea/",
          "result": "ok"
      "start": "2016-02-28T23:54:24.427000",
      "state": "success",
      "duration": 32,
      "id": "c361e5927d124d7dcf71a142dc0ec6d9b"
      "direction": "outgoing",
      "from": "+46766862344",
      "to": "+46723175800",
      "created": "2015-05-20T11:23:14.486000",
      "actions": [
          "connect": "+46734082791",
          "result": "success"
      "start": "2015-05-20T11:23:34.156000",
      "state": "success",
      "cost": 15800,
      "duration": 17,
      "legs": [
          "duration": 6,
          "to": "+46734082791",
          "state": "success",
          "from": "+46766862344"
      "id": "c10d90e4fcd7d976360509fdec5049e81"
      "direction": "outgoing",
      "from": "+46723175800",
      "to": "+46766861524",
      "created": "2015-03-17T12:03:37.745000",
      "actions": [
          "hangup": "busy"
      "state": "busy",
      "id": "c451f1dd5233fb9af000290e9f24712c0"


Show details about your account. Shows account balance, currency for your account and what phone number was used when registrating the account.

GET https://api.46elks.com/a1/me

Example of a reply:

  "mobilenumber": "+46766861004",
  "displayname": "46elks",
  "currency": "SEK",
  "balance": 2000000

SEK 2000000 amounts to 200SEK (200 * 100 * 100).


Are many different customers using the services you have built using 46elks? Subaccounts allow you to separate your different customers within the 46elks platform. Subaccounts have their own 46elks numbers and traffic history, isolated from other subaccounts.

As expected, subaccounts use 46elks credits from your main 46elks account.

Adding a subaccount

In order to create a new subaccount, simply make an HTTP POST to the /Subaccounts resource. The only mandatory key when creating a new subaccount is the key “name”.

POST https://api.46elks.com/a1/Subaccounts

Key Value
name Sample Customer AB

The reply will look like this:

  "id": "a123457da5678d894a6dafb1212b1ca12",
  "secret": "A347215F5F799B814462C37694D2383D",
  "name": "Sample Customer AB",
  "balanceused": 0

Using a subaccount

The keys “id” and “secret” is the new API username and API password you should use in order to access the 46elks API for this subaccount. Use these API credentials when you want to make API requests for the subaccount.

Subaccounts are isolated from each other, and there is no way for a subaccount to access information about the main account. It is thus possible to safely deploy the subaccount credentials to a customers server or application.

Can I limit how much credit a subaccount can use?

Yes, make an HTTP POST to the specific subaccount’s resource and set “usagelimit” to the requested value. Once this is set and “balanaceused” reach “usagelimit”, credit consumption for this subaccount will be denied

POST https://api.46elks.com/a1/Subaccounts/a123457da5678d894a6dafb1212b1ca12

Key Value
name New Name AB
usagelimit 200000

As usual, your setting is returned in the reply if set successfully:

  "id": "a123457da5678d894a6dafb1212b1ca12",
  "secret": "A347215F5F799B814462C37694D2383D",
  "name": "New Name AB",
  "balanceused": 7000,
  "usagelimit": 200000

The value of the number used in usagelimit depends on the currency set in your account. If you’re using €, and want to set the total usage limit for this account to 200€, you’d set the usagelimit to 2000000 (200 * 100 * 100)

If you’re using for example SEK, and you want to limit the account to 200:-, you’d also set the usagelimit to 2000000 (200 * 100 * 100)


You can test your API requests using the API console and the webhook console. The consoles are based on the Open API/Swagger specification of the 46elks API.

If you are using Postman to test your API requests you can use our Postman collection to get easy access to all API methods and parameters.


In case of an error, you will receive a 403 Forbidden or 404 Not found reply. Error descriptions are sent in plain text in the HTTP content.

Missing key from

If you’re getting the “missing key from” error it is likely that you’re sending in data in an unexpected format. When sending a text message you’re sending in atleast three keys: “from”, “to” and “message”. Make sure you’re submitting data using the application/x-www-form-urlencoded format.


You can always reach out and ask for help through help@46elks.com.