APIs that document themselves.
Every VeloGroup product ships a clean REST API with public documentation. Test in the tools you already use.
Pick a product
A copy-paste sample plus a link to the full docs. Each product has its own auth scheme — see the snippets below.
VeloConnect API
v1SMS, voice, WhatsApp, Viber, Telegram. REST + webhooks.
curl -X POST https://api.veloconnect.me/api/SendSMS \
-H "Content-Type: application/json" \
-d '{
"api_id": "YOUR_API_KEY",
"phonenumber": "37491000000",
"sender_id": "VeloGroup",
"sms_type": "P",
"encoding": "U",
"textmessage": "Your verification code: 482910",
"ValidityPeriodInSeconds": "3600"
}'
const resp = await fetch("https://api.veloconnect.me/api/SendSMS", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
api_id: process.env.VC_API_KEY,
phonenumber: "37491000000",
sender_id: "VeloGroup",
sms_type: "P",
encoding: "U",
textmessage: "Your verification code: 482910",
ValidityPeriodInSeconds: "3600",
}),
});
console.log(await resp.json());
import os, requests
resp = requests.post(
"https://api.veloconnect.me/api/SendSMS",
json={
"api_id": os.environ["VC_API_KEY"],
"phonenumber": "37491000000",
"sender_id": "VeloGroup",
"sms_type": "P",
"encoding": "U",
"textmessage": "Your verification code: 482910",
"ValidityPeriodInSeconds": "3600",
},
timeout=10,
)
resp.raise_for_status()
print(resp.json())
<?php
$response = wp_remote_post('https://api.veloconnect.me/api/SendSMS', [
'headers' => [ 'Content-Type' => 'application/json' ],
'body' => json_encode([
'api_id' => getenv('VC_API_KEY'),
'phonenumber' => '37491000000',
'sender_id' => 'VeloGroup',
'sms_type' => 'P',
'encoding' => 'U',
'textmessage' => 'Your verification code: 482910',
'ValidityPeriodInSeconds' => '3600',
]),
'timeout' => 10,
]);
print_r(json_decode(wp_remote_retrieve_body($response), true));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
func main() {
body, _ := json.Marshal(map[string]string{
"api_id": os.Getenv("VC_API_KEY"),
"phonenumber": "37491000000",
"sender_id": "VeloGroup",
"sms_type": "P",
"encoding": "U",
"textmessage": "Your verification code: 482910",
"ValidityPeriodInSeconds": "3600",
})
req, _ := http.NewRequest("POST", "https://api.veloconnect.me/api/SendSMS", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}
VeloeSIM API
v1eSIM ordering, activation, usage tracking.
curl "https://api.veloesim.com:2053/api/wholesale/plans?limit=6&offset=0" \
-H "Authorization: Apikey YOUR_API_KEY"
const resp = await fetch(
"https://api.veloesim.com:2053/api/wholesale/plans?limit=6&offset=0",
{ headers: { Authorization: `Apikey ${process.env.VE_API_KEY}` } },
);
const { count, rows } = await resp.json();
console.log(`${count} plans`);
rows.forEach(p => {
const area = p.areas[0]?.name ?? "—";
console.log(p.id, area, `${p.dataAmount}MB`, `${p.duration}d`, `$${p.price}`);
});
import os, requests
resp = requests.get(
"https://api.veloesim.com:2053/api/wholesale/plans",
params={"limit": 6, "offset": 0},
headers={"Authorization": f"Apikey {os.environ['VE_API_KEY']}"},
timeout=10,
)
resp.raise_for_status()
data = resp.json()
print(f"{data['count']} plans")
for p in data["rows"]:
area = p["areas"][0]["name"] if p["areas"] else "—"
print(p["id"], area, f"{p['dataAmount']}MB", f"{p['duration']}d", f"${p['price']}")
<?php
$response = wp_remote_get(
'https://api.veloesim.com:2053/api/wholesale/plans?limit=6&offset=0',
[
'headers' => [ 'Authorization' => 'Apikey ' . getenv('VE_API_KEY') ],
'timeout' => 10,
]
);
$data = json_decode(wp_remote_retrieve_body($response), true);
echo "{$data['count']} plans\n";
foreach ($data['rows'] as $p) {
$area = $p['areas'][0]['name'] ?? '—';
echo "{$p['id']} {$area} {$p['dataAmount']}MB {$p['duration']}d \${$p['price']}\n";
}
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type Area struct {
Name string `json:"name"`
}
type Plan struct {
ID int `json:"id"`
DataAmount int `json:"dataAmount"`
Duration int `json:"duration"`
Price float64 `json:"price"`
Areas []Area `json:"areas"`
}
func main() {
req, _ := http.NewRequest("GET", "https://api.veloesim.com:2053/api/wholesale/plans?limit=6&offset=0", nil)
req.Header.Set("Authorization", "Apikey "+os.Getenv("VE_API_KEY"))
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var out struct {
Count int `json:"count"`
Rows []Plan `json:"rows"`
}
json.NewDecoder(resp.Body).Decode(&out)
fmt.Printf("%d plans\n", out.Count)
for _, p := range out.Rows {
area := "—"
if len(p.Areas) > 0 {
area = p.Areas[0].Name
}
fmt.Printf("%d %s %dMB %dd $%.2f\n", p.ID, area, p.DataAmount, p.Duration, p.Price)
}
}
VeloVerify API
v1HLR, MNP, and IRSF lookups for number validity, carrier, and risk scoring.
curl "https://verify.veloconnect.me/v1/hlr/37491234567" \
-H "X-API-Key: YOUR_API_KEY"
const resp = await fetch(
"https://verify.veloconnect.me/v1/hlr/37491234567",
{ headers: { "X-API-Key": process.env.VV_API_KEY } },
);
const data = await resp.json();
console.log(data.countryCode, data.currentCarrierName, data.numberStatus);
import os, requests
resp = requests.get(
"https://verify.veloconnect.me/v1/hlr/37491234567",
headers={"X-API-Key": os.environ["VV_API_KEY"]},
timeout=10,
)
resp.raise_for_status()
data = resp.json()
print(data["countryCode"], data["currentCarrierName"], data["numberStatus"])
<?php
$response = wp_remote_get(
'https://verify.veloconnect.me/v1/hlr/37491234567',
[
'headers' => [ 'X-API-Key' => getenv('VV_API_KEY') ],
'timeout' => 10,
]
);
$data = json_decode(wp_remote_retrieve_body($response), true);
echo "{$data['countryCode']} {$data['currentCarrierName']} {$data['numberStatus']}";
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://verify.veloconnect.me/v1/hlr/37491234567", nil)
req.Header.Set("X-API-Key", os.Getenv("VV_API_KEY"))
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var data struct {
CountryCode string `json:"countryCode"`
CurrentCarrierName string `json:"currentCarrierName"`
NumberStatus string `json:"numberStatus"`
}
json.NewDecoder(resp.Body).Decode(&data)
fmt.Println(data.CountryCode, data.CurrentCarrierName, data.NumberStatus)
}
VeloPBX
Coming soonCloud virtual PBX. The public API is in development — start from the product page in the meantime.
See product page ↗What every API call has in common.
Errors
All errors return JSON with a code, a message, and a stable request_id for support escalation. HTTP status reflects the class — 4xx for client problems, 5xx for ours.
- Stable error codes
- request_id in every response
- Per-product error catalogues in the linked docs
Idempotency
Send Idempotency-Key: <uuid> on retryable POSTs. We replay the original response within a 24-hour window.
- 24-hour replay window
- Per-account uniqueness
- Safe for network retries
Rate limits
Quotas are commercial — set per account on the wholesale contract. Burst above quota is silently shaped before it is rejected.
- Quotas defined by contract
- Burst-shaping before 429
- 429 includes Retry-After header
Build with confidence before you ship.
Webhooks
Signed payloads (HMAC-SHA256, header X-Fortis-Signature). Retries on 5xx and network failure with exponential backoff, up to 24 hours.
- HMAC-SHA256 signing
- Exponential retry · 24h max
- Per-product event catalogues
Sandbox
Full test credentials within one business day of an NDA. Sandbox SMPP binds and SIP test endpoints mirror production behavior.
- SMPP + SIP sandbox
- Test DIDs + numbers
- No production billing
Where to get answers
Technical questions (REST API, webhooks)
- [email protected]
- 1 business day
Critical production issues
- pager
- 1-hour response
Sales and pricing questions
- [email protected]
- 4 hours
General inquiries
- /contact/
- 1 business day
Quick answers.
How do I get API keys?
Talk to wholesale via /contact/. We issue per-product keys after KYC. There is no self-serve signup at this time.
What are your rate limits?
Quotas are commercial and live on your wholesale contract. The platform shapes burst above quota before it returns 429 so you can plan around predictable headroom.
Do you support webhooks?
Yes — HMAC-SHA256 signed, with exponential retry up to 24 hours. Per-product event catalogues live in each product's linked docs.
Where are your endpoints hosted?
EU + NA primary, with regional fallback. Latency-routed at the edge. Per-product host is shown in the curl samples above.
Do you publish an OpenAPI spec?
Per product, where the upstream documentation site supports it (e.g. VeloVerify via Fern). Linked from each product card above.
How do I escalate during an incident?
Wholesale partners have a named carrier-ops contact and a 24×7 NOC pager. The technical support row in the support table above is for non-incident issues.
Ready to start building?
Grab API keys, kick the tires on our APIs, and graduate to production when you are ready.