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/.
1.1 Sign up
Sign up here. The response confirms your account number; your API token is emailed to you, not returned on the call. Accounts start on the free Bronze tier.
| Resource URL | https://app.primalconnect.com/api/signup |
|---|---|
| HTTP method | POST |
| Description | Create a Primal Connect account and email its API token |
| Content types | application/json or application/x-www-form-urlencoded |
| Request fields |
firstname, lastname,
email - all required. password is optional, and the sign-up form no longer asks for one: the account is used through its token, never through a password login. If you do send one it must be 8 characters or more, and password2 must match it when supplied. |
| Response fields |
status, message,
timestamp, accountid,
emailfrom - the address the token email arrives from. There is deliberately no token field. |
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"
}'
Example response:
{
"timestamp": "2026-09-29 09:24:11.403 -0400",
"status": 201,
"message": "Account created. Your account number is 0900000007. We have emailed your API token from contact@bigplanettelecom.com - it is not shown here.",
"accountid": "0900000007",
"emailfrom": "contact@bigplanettelecom.com"
}
Account numbers are ten digits beginning 09. They identify the account; they are not dialable numbers. No North American area code begins with a zero, so they can never collide with a real number.
One account per email address - a repeat address answers status 409. Sign-up is also rate limited per IP address, which answers status 429.
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.
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 emailed to you at sign-up. Send it as a token request header:
token: <your token>
The token may also be passed as a token field in the request body instead. Send it one way or the other, not both - if both are present, which one is used depends on the content type: a application/x-www-form-urlencoded request takes the header, a application/json request takes the body.
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.
Lost your token? We cannot show it to you again - search your mail for the message from contact@bigplanettelecom.com, or email support1@primaltech.com and we will reissue one.
1.5 Response codes
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. On
/api/sms this means no token was supplied.
401 - the token was not accepted. On
/api/sms it did not resolve to an account allowed to
send from the from number (see 2.1).
402 - the account has no remaining funds (see 2.1).
409 - that email address is already registered.
429 - rate limited. On /api/sms
this means the monthly allowance for your tier is spent (see 2.3); on
/api/signup it means too many attempts from one
IP address.
500 - unexpected error on our side.
503 - the endpoint is switched off on this server. On
/api/sms the SMS API is not enabled; on
/api/signup 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 URL | https://app.primalconnect.com/api/sms |
|---|---|
| HTTP method | POST |
| Description | Send a text message |
| Custom headers | token: <your token> |
| Content types | application/json or application/x-www-form-urlencoded |
| Request fields |
from - required. The 10-digit number the message is
sent from. It must be a number on your account to - required. The 10-digit destination number text - required. The message body token - optional. Your API token, if you are not sending it as the token header. Send it one way or the other, not both (see 1.4) |
Every response carries timestamp, status and message. Read status out of the body - it is the result of your request. The HTTP status line is always 200 for this endpoint.
{
"timestamp": "2026-09-28 09:24:11.403 -0400",
"status": 200,
"message": "Text Message Sent Successfully."
}
The values /api/sms answers in status:
| status | Meaning | What to do |
|---|---|---|
| 200 | The message was accepted for delivery. | - |
| 400 | No token was supplied, in the header or the body. | Send the token header. |
| 401 | The token does not identify an account that can send from this from number. | Check the token, and that from is a number on your account. |
| 402 | The account has no remaining funds. | Top the account up, or contact sales@primaltech.com. |
| 429 | The monthly message allowance for your tier is used up. The message names the tier, the allowance and when it resets. See 2.3. | Wait for the reset, or change tier. |
| 500 | The message could not be accepted. | Safe to retry. If it persists, contact support with the timestamp. |
| 503 | The SMS API is not enabled on this server. | Contact info@primaltech.com. |
A failure has the same shape as a success:
{
"timestamp": "2026-10-05 14:08:13.369 -0400",
"status": 401,
"message": "Message not sent. The token does not identify an account that can send from this number."
}
2.1.1 curl example request
curl -X POST https://app.primalconnect.com/api/sms \
-H "token: <your token>" \
-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: <your token>" \
-d "from=4165555555&to=4165558888&text=This is Primal Connect API"
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"
}
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.
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 URL | https://app.primalconnect.com/api/sms |
|---|---|
| HTTP method | GET |
| Description | Retrieve messages queued for your account |
| Query parameters | token - your token |
curl "https://app.primalconnect.com/api/sms?token=<your token>"
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"
}
2.3 Monthly allowance
Each account has a monthly message allowance set by its tier. Inbound and outbound messages both count against it.
| Bronze | 10,000 messages per calendar month |
|---|---|
| Silver | 5,000,000 messages per calendar month |
| Gold | 50,000,000 messages per calendar month |
The allowance is checked before the message is sent, so a message over the cap is never delivered and never billed. Once it is spent, /api/sms answers status 429 with a message naming your tier:
{
"timestamp": "2026-09-29 11:02:18.154 -0400",
"status": 429,
"message": "Monthly message allowance reached for the BRONZE tier (10000 messages). It resets at the start of next month. Contact sales@primaltech.com to change tier."
}
The counter resets at the start of the next calendar month, in server local time. To move tier before then, email sales@primaltech.com.