Ուղարկեք ձեր առաջին SMS-ը 10 րոպեում
Ստացեք API բանալի, գրանցեք Ալիաս (Sender ID), ուղարկեք մեկ հարցում, մշակեք առաքման ստացականը։ Ալիասի հաստատումը Հայաստանում տևում է մինչև 2 շաբաթ (միջազգային երթուղիների համար ավելի երկար) — հենց որ այն տրվում է, դուք production-ready եք առաջին կանչից։
Չորս պարտադիր նախադրյալ
VeloConnect API բանալի — մուտք գործեք ձեր <a href="https://dashboard.veloconnect.me/">VeloConnect կառավարման վահանակ</a> և պատճենեք <code>api_id</code>-ն, կամ բացեք նոր հաշիվ երկու րոպեում։
Հաստատված Ալիաս (միջազգային եզրույթ՝ Sender ID) — ձեր գրանցված ապրանքանիշի անունը՝ նպատակային երթուղում։ Ալիասի գրանցումը պարտադիր է VeloConnect-ի սպասարկած ցանկացած շուկայում (A2P տրաֆիկի համար թվային պահեստային չկա)։ Պլանավորեք նախապես՝ Հայաստանը հաստատում է ~2 շաբաթում՝ ամբողջական փաստաթղթերի ներկայացումից հետո; միջազգային շուկաները տևում են ավելի երկար։ Պորտալը ուղեկցում է գործընթացով — տեսեք Քայլ 0-ը ստորև։
Ֆինանսավորված հաշվի մնացորդ — հենց որ Ալիասը հաստատվում է, լրացրեք ձեր VeloConnect դրամապանակը պորտալից։ Ապահովված են և՛ Քարտով, և՛ Բանկային փոխանցումով վճարումները; փոքր թեստային գումարը բավարար է առաջին փաթեթը ուղարկելու և առաքելիությունը end-to-end ստուգելու համար՝ նախքան մասշտաբը մեծացնելը։
Մեկ E.164 ֆորմատի ստացողի հեռախոսահամար, որը կարող եք ստուգել, և տերմինալ, Node, Python կամ ինչ էլ որ առաջինը ձեռքի տակ ունեք։
Երեք քայլ դեպի կենդանի SMS
-
Ուղարկեք ձեր առաջին SMS-ը
Մեկ GET հարցում հինգ պարամետրով։ Կարգավիճակը վերադառնում է սինխրոն — message_id, sent | queued | failed, և ստացողի մեկ միավորի արժեքը։
-
Մշակեք առաքման ստացականը
Բարձրացրեք webhook endpoint։ VeloConnect-ը POST է անում delivered / failed / expired կարգավիճակ՝ երբ օպերատորները հետադարձ կապ են հայտնում։
-
Ուղարկեք ցուցակին (cascading)
Նույն payload-ը, մի քանի ալիք։ WhatsApp → Viber → SMS — ավտոմատ պահեստային անցում, վճարում միայն առաջին հաջող առաքման համար։
message_id, status, client_costs
Սինխրոն պատասխանը պարունակում է չորս դաշտ, որոնք պետք է պահեք. <code>message_id</code> — ձեր հանգույցը կարգավիճակային webhook-ների և հաշվետվությունների համար; <code>status</code> — queued, sent, failed կամ rejected; <code>client_costs</code> — ստացողի մեկ միավորի արժեքը ձեր հաշվի արժույթով; <code>uid</code> — օպերատորի վերադարձրած նույնականացուցիչը, երբ ընդունեց հաղորդագրությունը։
Պահեք <code>message_id</code>-ն — դուք դրա հետ կհամապատասխանեցնեք, երբ DLR webhook-ը կարձագանքի վերջնական կարգավիճակով։
Webhook, որի մեջ ապրում է ձեր օպերատորի-կարգավիճակի տրամաբանությունը
SendSMS կանչին տեղադրեք callback_url (կամ կարգավորեք լռելյայնը հաշվի համար), և VeloConnect-ը POST է անում ստացականը որպես JSON հենց որ օպերատորները ավարտում են հաղորդագրությունը։ Հաստատեք HTTP 200-ով — մենք կրկնում ենք 5xx-ի դեպքում։
<?php
// Vanilla PHP — POST endpoint at /dlr.
// VeloConnect posts the receipt as JSON. Acknowledge fast (HTTP 200).
$body = json_decode( file_get_contents( 'php://input' ), true );
if ( ! isset( $body['message_id'], $body['status'] ) ) {
http_response_code( 400 );
exit;
}
// Payload shape:
// message_id string — your handle from SendSMS
// status string — delivered | failed | expired | unknown
// phonenumber string — recipient E.164
// timestamp string — ISO-8601 terminal-state time
// error_code int|null — set when status != delivered
switch ( $body['status'] ) {
case 'delivered':
// Persist final state, fire downstream event, etc.
break;
case 'failed':
case 'expired':
error_log( "SMS {$body['message_id']} {$body['status']} code={$body['error_code']}" );
break;
}
http_response_code( 200 );
// Express — POST /dlr
import express from 'express';
const app = express();
app.use(express.json());
app.post('/dlr', (req, res) => {
const { message_id, status, phonenumber, timestamp, error_code } = req.body;
if (!message_id || !status) return res.sendStatus(400);
switch (status) {
case 'delivered':
// persist terminal state
break;
case 'failed':
case 'expired':
console.warn(`SMS ${message_id} ${status} code=${error_code}`);
break;
}
// Respond fast — VeloConnect retries on 5xx.
res.sendStatus(200);
});
app.listen(3000);
# pip install fastapi uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
class DLR(BaseModel):
message_id: str
status: str # delivered | failed | expired | unknown
phonenumber: str
timestamp: str
error_code: Optional[int] = None
@app.post("/dlr")
async def receive_dlr(body: DLR):
if body.status == "delivered":
# persist terminal state
pass
elif body.status in {"failed", "expired"}:
# log error_code for support escalation
pass
return {"ok": True}
Կարգավիճակի արժեքները՝ delivered · failed · expired · unknown։ error_code-ը սահմանվում է, երբ կարգավիճակը delivered-ից տարբեր է։
Փորձեք ամենաէժան ալիքը առաջինը, ավտոմատ անցում պահեստայինի
Մեկ հարցում, երեք փորձ։ WhatsApp → Viber → SMS, cascadingPriorityLevel-ով կարգավորվող հերթականությամբ։ Վճարում եք միայն առաջին հաջող առաքման համար։
curl -X POST 'https://api.veloconnect.me/api/partners/campaigns/cascading' \
-H 'api_id: YOUR_API_ID' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"name": "Order #4821 confirmation",
"scheduleDate": "2026-05-04T16:00:00Z",
"timezone": 4,
"timezoneId": "Asia/",
"campaignContacts": [
{
"firstName": "Anna",
"lastName": "Petrosyan",
"phoneNumber": "+1 289 963 1055",
"email": "[email protected]"
}
],
"campaigns": [
{
"communicationType": "WHATSAPP",
"providerType": "META",
"templateId": "order_confirmation_v3",
"senderId": "Fortis",
"cascadingPriorityLevel": 1
},
{
"communicationType": "VIBER",
"providerType": "RAKUTEN",
"message": "Hi {firstName}, your order #4821 ships today.",
"senderId": "Fortis",
"cascadingPriorityLevel": 2
},
{
"communicationType": "SMS",
"providerType": "DIRECT",
"message": "Hi {firstName}, your order #4821 ships today.",
"senderId": "Fortis",
"cascadingPriorityLevel": 3
}
]
}'
// Node 18+ — global fetch
const payload = {
name: 'Order #4821 confirmation',
scheduleDate: '2026-05-04T16:00:00Z',
timezone: 4,
timezoneId: 'Asia/',
campaignContacts: [
{ firstName: 'Anna', lastName: 'Petrosyan', phoneNumber: '+1 289 963 1055', email: '[email protected]' },
],
campaigns: [
{ communicationType: 'WHATSAPP', providerType: 'META', templateId: 'order_confirmation_v3', senderId: 'Fortis', cascadingPriorityLevel: 1 },
{ communicationType: 'VIBER', providerType: 'RAKUTEN', message: 'Hi {firstName}, your order #4821 ships today.', senderId: 'Fortis', cascadingPriorityLevel: 2 },
{ communicationType: 'SMS', providerType: 'DIRECT', message: 'Hi {firstName}, your order #4821 ships today.', senderId: 'Fortis', cascadingPriorityLevel: 3 },
],
};
const res = await fetch('https://api.veloconnect.me/api/partners/campaigns/cascading', {
method: 'POST',
headers: {
api_id: process.env.VELOCONNECT_API_ID,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error(`Cascading ${res.status}`);
console.log(await res.json());
# pip install httpx
import os
import httpx
payload = {
"name": "Order #4821 confirmation",
"scheduleDate": "2026-05-04T16:00:00Z",
"timezone": 4,
"timezoneId": "Asia/",
"campaignContacts": [
{"firstName": "Anna", "lastName": "Petrosyan",
"phoneNumber": "+1 289 963 1055", "email": "[email protected]"},
],
"campaigns": [
{"communicationType": "WHATSAPP", "providerType": "META",
"templateId": "order_confirmation_v3", "senderId": "Fortis",
"cascadingPriorityLevel": 1},
{"communicationType": "VIBER", "providerType": "RAKUTEN",
"message": "Hi {firstName}, your order #4821 ships today.",
"senderId": "Fortis", "cascadingPriorityLevel": 2},
{"communicationType": "SMS", "providerType": "DIRECT",
"message": "Hi {firstName}, your order #4821 ships today.",
"senderId": "Fortis", "cascadingPriorityLevel": 3},
],
}
resp = httpx.post(
"https://api.veloconnect.me/api/partners/campaigns/cascading",
json=payload,
headers={
"api_id": os.environ["VELOCONNECT_API_ID"],
"Accept": "application/json",
},
timeout=15,
)
resp.raise_for_status()
print(resp.json())
<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';
$payload = [
'name' => 'Order #4821 confirmation',
'scheduleDate' => '2026-05-04T16:00:00Z',
'timezone' => 4,
'timezoneId' => 'Asia/',
'campaignContacts' => [[
'firstName' => 'Anna',
'lastName' => 'Petrosyan',
'phoneNumber' => '+1 289 963 1055',
'email' => '[email protected]',
]],
'campaigns' => [
[
'communicationType' => 'WHATSAPP',
'providerType' => 'META',
'templateId' => 'order_confirmation_v3',
'senderId' => 'Fortis',
'cascadingPriorityLevel' => 1,
],
[
'communicationType' => 'VIBER',
'providerType' => 'RAKUTEN',
'message' => 'Hi {firstName}, your order #4821 ships today.',
'senderId' => 'Fortis',
'cascadingPriorityLevel' => 2,
],
[
'communicationType' => 'SMS',
'providerType' => 'DIRECT',
'message' => 'Hi {firstName}, your order #4821 ships today.',
'senderId' => 'Fortis',
'cascadingPriorityLevel' => 3,
],
],
];
$client = new GuzzleHttp\Client();
$res = $client->post('https://api.veloconnect.me/api/partners/campaigns/cascading', [
'headers' => [
'api_id' => getenv('VELOCONNECT_API_ID'),
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
'json' => $payload,
]);
print_r(json_decode($res->getBody(), true));
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
type contact struct {
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
PhoneNumber string `json:"phoneNumber"`
Email string `json:"email"`
}
type campaign struct {
CommunicationType string `json:"communicationType"`
ProviderType string `json:"providerType"`
Message string `json:"message,omitempty"`
TemplateID string `json:"templateId,omitempty"`
SenderID string `json:"senderId"`
CascadingPriorityLevel int `json:"cascadingPriorityLevel"`
}
type cascadeRequest struct {
Name string `json:"name"`
ScheduleDate string `json:"scheduleDate"`
Timezone int `json:"timezone"`
TimezoneID string `json:"timezoneId"`
CampaignContacts []contact `json:"campaignContacts"`
Campaigns []campaign `json:"campaigns"`
}
func main() {
body := cascadeRequest{
Name: "Order #4821 confirmation",
ScheduleDate: "2026-05-04T16:00:00Z",
Timezone: 4,
TimezoneID: "Asia/",
CampaignContacts: []contact{{
FirstName: "Anna", LastName: "Petrosyan",
PhoneNumber: "+1 289 963 1055", Email: "[email protected]",
}},
Campaigns: []campaign{
{CommunicationType: "WHATSAPP", ProviderType: "META",
TemplateID: "order_confirmation_v3", SenderID: "Fortis",
CascadingPriorityLevel: 1},
{CommunicationType: "VIBER", ProviderType: "RAKUTEN",
Message: "Hi {firstName}, your order #4821 ships today.",
SenderID: "Fortis", CascadingPriorityLevel: 2},
{CommunicationType: "SMS", ProviderType: "DIRECT",
Message: "Hi {firstName}, your order #4821 ships today.",
SenderID: "Fortis", CascadingPriorityLevel: 3},
},
}
buf, _ := json.Marshal(body)
req, _ := http.NewRequest("POST",
"https://api.veloconnect.me/api/partners/campaigns/cascading",
bytes.NewReader(buf))
req.Header.Set("api_id", os.Getenv("VELOCONNECT_API_ID"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
fmt.Println(res.Status)
}
// Java 11+ — java.net.http
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Cascading {
public static void main(String[] args) throws Exception {
String body = """
{
"name": "Order #4821 confirmation",
"scheduleDate": "2026-05-04T16:00:00Z",
"timezone": 4,
"timezoneId": "Asia/",
"campaignContacts": [
{"firstName":"Anna","lastName":"Petrosyan",
"phoneNumber":"+1 289 963 1055","email":"[email protected]"}
],
"campaigns": [
{"communicationType":"WHATSAPP","providerType":"META",
"templateId":"order_confirmation_v3","senderId":"Fortis",
"cascadingPriorityLevel":1},
{"communicationType":"VIBER","providerType":"RAKUTEN",
"message":"Hi {firstName}, your order #4821 ships today.",
"senderId":"Fortis","cascadingPriorityLevel":2},
{"communicationType":"SMS","providerType":"DIRECT",
"message":"Hi {firstName}, your order #4821 ships today.",
"senderId":"Fortis","cascadingPriorityLevel":3}
]
}
""";
HttpRequest req = HttpRequest.newBuilder(
URI.create("https://api.veloconnect.me/api/partners/campaigns/cascading"))
.header("api_id", System.getenv("VELOCONNECT_API_ID"))
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.statusCode());
System.out.println(res.body());
}
}
Ժամանակացույց, կոնտակտային ցուցակներ, ալիքային տեմպլեյթներ և սակագների պլաններ — մեկ payload-ում։
Երբ API-ն հակադարձ խոսում է
Ալիասը հաստատված չէ
API-ն վերադարձնում է 400՝ error.code=invalid_sender_id-ով, երբ Ալիասը (Sender ID) չի հաստատվել նպատակային երթուղում։ Բացեք Senders-ը VeloConnect պորտալում — հաստատվածները ցույց են տալիս կանաչ Approved բեյջ և Date Approved։ Եթե հարցումը դեռ Pending է, սպասեք ~2 շաբաթ Հայաստանի համար և ավելի երկար՝ միջազգային երթուղիների համար; եթե Rejected է, ձեր AM-ը ունի օպերատորի մեկնաբանությունները։
Կոդավորումը 70 նիշով սահմանափակվում է
Լռելյայն encoding=T (GSM-7) տեղավորում է 160 նիշ մեկ սեգմենտում։ Անցեք encoding=U (UCS-2)՝ կիրիլյան, հայերեն կամ emoji-ի համար — բայց հետևեք 70 նիշի սահմանին մեկ սեգմենտում։ API-ն ավելի երկար տեքստերը ավտոմատ բաժանում է իրար կապակցված սեգմենտների և համապատասխանաբար գանձում։
Արգելափակված ստացող
Որոշ MSISDN-ներ մերժում են A2P SMS-ները (DND ցուցակներ, տեղափոխված համարներ, կարգավորիչի արգելափակումներ)։ Օգտագործեք cascading endpoint-ը՝ Viber կամ WhatsApp ավտոմատ պահեստային անցման համար։ Վճարում եք միայն առաջին հաջող ալիքի համար։
Rate limit (429)
Հաշվի լռելյայն TPS-ը 30 հաղորդագրություն/վայրկյանն է։ Pro պլանների վրա հասանելի է 100 TPS-ի թռիչք։ Գերազանցելու դեպքում API-ն վերադարձնում է 429՝ Retry-After-ով — հետ քաշվեք և կրկնեք էքսպոնենցիալ ուշացմամբ։
Production-ի պատասխանները
Ինչպե՞ս գրանցել Ալիասը։
Ալիասի (Sender ID) գրանցումը կատարվում է VeloConnect պորտալից — <a href="https://dashboard.veloconnect.me/">dashboard.veloconnect.me</a> → Senders → New Request։ Ընտրեք նպատակային Country և Operator-ը, Sender Name-ում գրեք ձեր alphanumeric ապրանքանիշի անունը (օրինակ՝ <code>Fortis</code>) — սա ձեր Ալիասն է, ընտրեք Local կամ International SID Type, ավելացրեք կարճ հիմնավորում (մինչև 280 նիշ), և վերբեռնեք երեք փաստաթուղթ՝ Registration Form (Excel, ≤3 ՄԲ), Letter of Authorization (PDF, ≤3 ՄԲ), Company Certificate (PDF, ≤3 ՄԲ)։ Հարցման կարգավիճակը անցնում է Pending → Approved կամ Rejected՝ նպատակային օպերատորի և կարգավորիչի վերանայման հետևանքով։<br><br><strong>Ժամկետներ.</strong> Հայաստանը հաստատում է ~2 շաբաթում՝ ամբողջական փաստաթղթերի տեղական հեռախոսային ընկերության ստանալուց հետո։ Միջազգային երթուղիները (ԱՄՆ, Մեծ Բրիտանիա, ԵՄ, Հնդկաստան, Պարսից ծոց, APAC) տևում են ավելի երկար — տիպիկորեն մի քանի շաբաթից մինչև մի քանի ամիս՝ կախված կարգավորիչից։ Եթե փաստաթղթերի պատրաստման համար օգնության կարիք ունեք, գրեք <a href="mailto:[email protected]">[email protected]</a>՝ նպատակային շուկաների մասին, ձեր AM-ը կուղեկցի ձեզ գործընթացով։
Ինչպե՞ս ակտիվացնել հաշիվը Ալիասի հաստատումից հետո։
Հենց որ ձեր Ալիասը Senders ցուցակում ստանում է կանաչ <strong>Approved</strong> բեյջը, լրացրեք ձեր VeloConnect դրամապանակը պորտալից՝ նախքան որևէ տրաֆիկ ուղարկելը։ Ապահովված են և՛ <strong>Քարտով</strong>, և՛ <strong>Բանկային փոխանցումով</strong> վճարումները — ընտրեք այն, որն ավելի արագ է մաքրվում ձեր շուկայում։ Փոքր թեստային գումարը բավարար է առաջին փաթեթը ուղարկելու և առաքելիությունը end-to-end ստուգելու համար՝ նախքան մասշտաբը մեծացնելը; մեծ ավանդները բացում են ծավալային զեղչերը՝ <a href="/products/veloconnect/#pricing">/products/veloconnect/#pricing</a>-ում նկարագրված։ Հաշվապահության համար proforma հաշիվ-ապրանքագիր է անհրաժեշտ՞ — ձեր AM-ը կարող է տրամադրել, գրեք <a href="mailto:[email protected]">[email protected]</a>։
Sandbox կամ test mode ունե՞ք։
Առանձին sandbox չկա։ Ուղարկեք ձեր սեփական թեստային համարներին։ Մենք գանձում ենք յուրաքանչյուր հաղորդագրության համար, սակայն production սակագները ցենտեր են — end-to-end թեստավորումն արժե սուրճից քիչ։ Մեկնարկի համար ծավալային ստուգման դեպքում խնդրեք վաճառքի թիմին տրամադրել կրեդիտային սահմանաչափ։
Ինչպե՞ս հաշվել նիշերը կոդավորումներով։
GSM-7-ը (լռելյայն, <code>encoding=T</code>) տեղավորում է 160 նիշ մեկ սեգմենտում, դրանից բարձր ենթադրում է 153 նիշանոց կապակցված սեգմենտներ։ UCS-2-ը (կիրիլյան, հայերեն, emoji, <code>encoding=U</code>) տեղավորում է 70 նիշ մեկ սեգմենտում, կապակցման դեպքում՝ 67։ Հատուկ նիշեր, ինչպիսիք են <code>{ } [ ] ~ ^ \ | €</code>, GSM-7-ում հաշվվում են որպես երկու։ Ցանկացած open-source segment calculator կցուցադրի բաժանումը։
Ի՞նչ է նշանակում DLR-ի յուրաքանչյուր կարգավիճակ։
<code>delivered</code> — սարքն ստացման հաստատում տվեց։ <code>failed</code> — օպերատորը մերժեց; <code>error_code</code>-ը ասում է թե ինչու։ <code>expired</code> — օպերատորն ընդունեց, բայց չառաքեց վավերականության պահի ընթացքում (սովորաբար 24 ժամ)։ <code>unknown</code> — վերջնական կարգավիճակ չստացանք օպերատորից; հաշվարկի առումով դիտարկեք որպես failed։
Ինչպե՞ս ուղարկել 10,000 համարների՝ առանց սահմաններին հանդիպելու։
Երկու ճանապարհ։ (ա) Փաթեթ՝ cascading campaigns endpoint-ով — POST մեկ payload՝ <code>campaignContacts</code> մինչև 100k մուտքագրումներով; մենք ներքին կարգավորմամբ ենք զբաղվում throttling-ով։ (բ) Stream՝ SendSMS-ով ձեր TPS-ով — տիպիկ ձև տրանզակցիոն հոսքերի համար, որտեղ կարևոր է հերթականությունը։ 10k bulk ուղարկման համար օգտագործեք campaigns endpoint-ը և հետևեք մեկ քամպայնի DLR webhook-ին։
Պատրա՞ստ եք production-ին։
Գրանցեք ձեր Ալիասը VeloConnect պորտալում, կամ խոսեք երթուղման ինժեների հետ ձեր տրաֆիկի պրոֆիլի, Ալիասի գրանցման և ծավալային գնագոյացման մասին։