Skip to content
Primal Technologies Primal Connect

A Primal Technologies service

  1. Home
  2. API Reference
API reference

Primal Connect API

A REST API for sending and receiving SMS. Requests are ordinary HTTP calls, responses are JSON, and every call is authenticated with a token tied to your account. All endpoints live under https://app.primalconnect.com/api/.

Primal Connect is a REST API for sending and receiving SMS over the internet. Requests are ordinary HTTP calls, responses are JSON, and every call is authenticated with a token tied to your account.

All endpoints live under https://app.primalconnect.com/api/.

Changed: the API base address used to be documented as http://api.primalconnect.com/sms. That host is no longer the entry point. Use https://app.primalconnect.com/api/sms.

1.1 Sign up

Sign up here. Registration returns your account ID and your API token in the same response - there is no separate step to go and fetch a token afterwards.

Resource URLhttps://app.primalconnect.com/api/signup
HTTP methodPOST
DescriptionCreate a Primal Connect account and issue its API token
Content typesapplication/json or application/x-www-form-urlencoded
Request fields firstname, lastname, email, password (8 characters minimum), password2 (confirmation; required from the web form, optional for JSON callers)
Response fields status, message, timestamp, accountid, token

Example request:

curl -X POST https://app.primalconnect.com/api/signup \ -H "Content-Type: application/json" \ -d '{ "firstname": "Jane", "lastname": "Doe", "email": "jane@example.com", "password": "choose-a-strong-one" }'

Example response:

{ "timestamp": "2026-09-28 09:24:11.403 -0400", "status": 201, "message": "Account created. Send this token as the 'token' header on /api/sms.", "accountid": "00000041", "token": "8drj4eh3hp7mvci5" }

Store the token somewhere safe. It is the only credential needed to send messages on your account, and it is not shown again. If the email address is already registered the response comes back with status 409.

1.2 HTTP methods

Primal Connect uses two HTTP methods:

POST creates something - a new account, or a message to be sent.

GET reads something - queued inbound messages, or account details.

Changed: earlier versions of this page listed PUT and DELETE. The API does not implement them and never did; a PUT or DELETE will not be routed.

1.3 Data formats

Responses are always JSON.

Requests may be sent either as JSON (Content-Type: application/json) or as an ordinary HTML form post (Content-Type: application/x-www-form-urlencoded). Both are accepted on /api/sms and /api/signup, and the field names are the same either way. Earlier versions of this page said JSON was mandatory - it is not.

1.4 Token authentication

Every call is authenticated with the token issued at sign-up. Send it as a token request header:

token: 8drj4eh3hp7mvci5

The token may also be passed as a token field in the request body instead. If both are present, the body field wins.

Do not validate the token's length or character set. This page used to describe it as "a global unique 40-character token" (while the example beside it showed a 32-character one). Neither is a rule you should code against. The token is an opaque, case-sensitive string - store it and send it back exactly as issued.

Managed and carrier accounts continue to have their tokens provisioned through Skynet rather than through the sign-up form. The token behaves identically once issued.

1.5 Response codes

Read this before writing your error handling. The API answers with HTTP 200 on almost every call, including failures. The result you care about is the status field inside the JSON body. Branch on that, not on the HTTP status line.

Values you will see in the body's status field:

200 - the request succeeded.
201 - the resource was created; sign-up returns this.
400 - a required field is missing or malformed.
409 - that email address is already registered.
429 - too many requests; sign-up is rate limited.
500 - unexpected error on our side.
503 - self-serve sign-up is temporarily closed.

Every response also carries a human-readable message and a timestamp. When something fails, the message is the field to log and to show your users.

Using our API

2.1 Send SMS

Resource URLhttps://app.primalconnect.com/api/sms
HTTP methodPOST
DescriptionSend a text message
Custom headerstoken: <your token>
Content typesapplication/json or application/x-www-form-urlencoded
Request fields from - the 10-digit number the message is sent from
to - the 10-digit destination number
text - the message body
token - optional, if not sent as a header
Response { "timestamp": "2026-09-28 09:24:11.403 -0400", "status": 200, "message": "Text Message Sent Successfully." }
Changed: from is now required. This page previously listed the request as "to, text" only. A request without from will not be delivered.

2.1.1 curl example request

curl -X POST https://app.primalconnect.com/api/sms \ -H "token: 8drj4eh3hp7mvci5" \ -H "Content-Type: application/json" \ -d '{ "from": "4165555555", "to": "4165558888", "text": "This is Primal Connect API" }'

The same call as a form post:

curl -X POST https://app.primalconnect.com/api/sms \ -H "token: 8drj4eh3hp7mvci5" \ -d "from=4165555555&to=4165558888&text=This is Primal Connect API"

2.1.2 Java example code

Using Apache HttpComponents (org.apache.httpcomponents:httpclient):

CloseableHttpClient client = HttpClients.createDefault(); HttpPost post = new HttpPost("https://app.primalconnect.com/api/sms"); post.setHeader("token", "8drj4eh3hp7mvci5"); post.setHeader("Content-Type", "application/json"); String body = "{" + "\"from\":\"4165555555\"," + "\"to\":\"4165558888\"," + "\"text\":\"This is Primal Connect API\"" + "}"; post.setEntity(new StringEntity(body, "UTF-8")); try (CloseableHttpResponse response = client.execute(post)) { String json = EntityUtils.toString(response.getEntity()); // The HTTP status line is 200 even on failure - read the // "status" field out of the JSON body instead. See 1.5. System.out.println(json); }

2.2 Receive SMS

There are two ways to receive replies. Which one applies to your account depends on whether a callback URL has been configured for it in Skynet:

A callback URL is set - we POST each inbound message to that URL as it arrives. See 2.2.1.

No callback URL is set - inbound messages are queued for you and you collect them by polling. See 2.2.2.

Contact support1@primaltech.com to have a callback URL added to your account.

2.2.1 Callback URL

We send an HTTP POST to your URL. The body is JSON:

{ "from": "4165555555", "to": "4165558888", "text": "This is a replied text message from mobile", "systemReceivedTime": "2026-09-28 09:24:11.403" }
Two things to code around.

The request arrives with Content-Type: application/x-www-form-urlencoded even though the body is JSON. Read the raw request body and parse it as JSON - do not rely on your framework's form parsing, which will not decode it.

Your token is not included in the callback body. Authenticate the callback by whatever means suits your endpoint, such as a secret path segment.
Removed: this page used to describe a "GET callback URL" mode that appended the message as query parameters. That mode is not implemented. Every callback is a POST with a JSON body.

2.2.2 Polling for messages

If no callback URL is configured, inbound messages are held for you and returned by a GET on the same resource:

Resource URLhttps://app.primalconnect.com/api/sms
HTTP methodGET
DescriptionRetrieve messages queued for your account
Query parameterstoken - your token
curl "https://app.primalconnect.com/api/sms?token=8drj4eh3hp7mvci5"

Messages waiting:

{ "timestamp": "2026-09-28 09:24:11.403 -0400", "status": 200, "message": "Success, 1 messages", "result": [ { "from": "4165555555", "to": "4165558888", "text": "This is a replied text message from mobile", "systemReceivedTime": "2026-09-28 09:24:11.403" } ] }

Nothing waiting - note that result is absent rather than empty:

{ "timestamp": "2026-09-28 09:24:11.403 -0400", "status": 200, "message": "Success, No message" }
The queue is held in memory, so a restart of the service clears anything not yet collected. Poll often enough that this is not a problem for you, and use a callback URL if you cannot tolerate the loss.

Start sending in minutes

Registration is free and returns your API token straight away. The first 10,000 messages a month are on us.