واجهة REST والتكاملات
Intégrez AVIA ERP via l'API REST du portail, les endpoints publics et la synchronisation avec le site marketing.
البنية
L'API métier est exposée par avcore sur le portail portal.aviaerp.com. Le site marketing aviaerp.com proxie les routes publiques /api/v1/public/* vers le portail pour éviter les problèmes CORS côté navigateur.
Portail ERP (API principale) : https://portal.aviaerp.com/api/v1/
Landing (proxy public) : https://aviaerp.com/api/v1/public/
Landing (routes internes) : https://aviaerp.com/api/erp-sync
https://aviaerp.com/api/paddle/webhookالمصادقة
Les appels authentifiés utilisent un JWT obtenu via POST /api/v1/auth/login (e-mail + mot de passe ou SSO selon tenant). Incluez le token dans l'en-tête :
Authorization: Bearer <access_token>
X-Tenant: erppro
Content-Type: application/jsonLes intégrations serveur-à-serveur (sync landing, clés internes SaaS) utilisent X-API-Key avec la clé partagée SAAS_INTERNAL_API_KEY / LANDING_SYNC_API_KEY configurée des deux côtés.
مفاتيح API
Pour une intégration tierce (pas une session portail), créez une clé depuis Paramètres → Clés API — réservé aux rôles admin / super-admin. Le secret n'est affiché qu'une seule fois, à la création :
Authorization: Bearer avia_live_<prefixe>_<secret>
X-Tenant-ID: <votre_tenant>Une clé est cantonnée à un seul tenant (aucun tenant par défaut pour un appelant tiers) et porte des scopes — une paire par module acheté, module:read / module:write (l'écriture couvre la lecture), plus rules et webhooks pour ces deux surfaces hors modules facturés. Les droits réellement accordés sont le plus étroit entre les scopes de la clé et les rôles de son porteur — un scope ne fait que restreindre, jamais accorder plus que ce que le porteur a déjà. L'expiration est obligatoire, jusqu'à 1 an ; une clé révoquée ou expirée refuse immédiatement (cle_api_invalide). Une clé est refusée d'emblée si la requête porte un en-tête Origin — jamais utilisable depuis un navigateur.
La limite de débit est par clé (pas par utilisateur), en-têtes X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset sur chaque réponse, 600 req/min par défaut.
نقاط النهاية العمومية
أمثلة على نقاط نهاية متاحة دون جلسة مستخدم (حسب النشر):
| المسار | الاستخدام |
|---|---|
GET /api/v1/public/subscription-plans | خطط الأسعار المعروضة في /tarifs |
POST /api/contact | نموذج الاتصال (موقع Next.js) |
POST /api/demo | طلب عرض توضيحي |
المزامنة من النظام إلى الموقع
Le portail pousse périodiquement tenant, plans et métadonnées vers POST /api/erp-sync sur le landing. Configurez l'URL dans Paramètres → Accès portail :
URL sync (prod) : https://aviaerp.com/api/erp-sync
URL sync (local) : http://localhost:3030/api/erp-sync
Health check : GET .../api/erp-sync/healthLa clé LANDING_SYNC_API_KEY doit être identique sur le portail et dans .env.production du landing.
خطافات الويب
Paddle — configurez le webhook vers https://aviaerp.com/api/paddle/webhook pour les événements de transaction et d'abonnement.
Événements métier — abonnez-vous depuis Paramètres → Webhooks du portail à l'un des ~27 événements du catalogue (création de document, changement de statut, étapes d'approbation — la liste complète s'interroge sur GET /settings/webhooks/events et est documentée dans la section webhooks: du contrat OpenAPI). Chaque livraison est signée et porte :
X-Avia-Event: invoice.created
X-Avia-Delivery-Id: 6f1e2c3a-... # stable meme apres une relivraison manuelle
X-Avia-Timestamp: 1755792000
X-Avia-Webhook-Version: 2026-08-19
X-Avia-Signature: sha256=<hmac> # deux valeurs separees par une virgule pendant une rotationLa signature est un HMAC-SHA256 sur <timestamp>.<corps brut> avec le secret de l'abonnement — vérifiez-la et refusez tout ce qui dépasse une fenêtre de 5 minutes. Régénérez le secret à tout moment depuis l'écran de l'abonnement (Régénérer le secret) : l'ancien continue de signer en plus du nouveau pendant 24h (double signature ci-dessus), donc aucune livraison en vol n'échoue pendant une rotation. Une livraison en échec est reprise avec un backoff quadratique et peut être rejouée manuellement depuis le journal des livraisons (POST .../webhooks/{id}/deliveries/{did}/retry).
حزمة SDK بلغة TypeScript
@aviaerp/sdk (sdk/typescript/ dans le dépôt) enveloppe les types générés (openapi-typescript) d'un client HTTP typé (openapi-fetch) : nouvelle tentative automatique sur 429 qui respecte Retry-After, erreurs typées {code, params, message}, aides de filtre reprenant la syntaxe du CRUD générique, pagination itérable, et un utilitaire verifyWebhookSignature (Web Crypto, aucun secret serveur exposé à un navigateur). C'est aujourd'hui un paquet de workspace privé, pas encore publié sur un registre — consommé par copie du dossier en attendant.
import { createAviaClient } from "@aviaerp/sdk"
const client = createAviaClient({
baseUrl: "https://portal.aviaerp.com",
apiKey: process.env.AVIA_API_KEY!,
tenantId: "erppro",
})
const { data, error } = await client.GET("/api/v1/sales-orders", {
params: { query: { status: "eq.confirme", page_size: 20 } },
})المرجع الكامل (OpenAPI)
Toutes les routes au-delà des trois montrées ici — plus de 1000 chemins, générés depuis le code, jamais écrits à la main — se parcourent module par module, avec recherche, paramètres, schéma de réponse et un exemple de requête pour chacune :