Référence API

API publique Couverty

Accédez à vos données et intégrez Couverty dans vos applications.

Guide

Démarrage rapide

Créez une clé API et commencez à utiliser l'API en 3 étapes.

  1. 1

    Créer une clé API

    Accédez à vos paramètres d'intégration. Cliquez sur "Créer une clé API" et sélectionnez les permissions requises (restaurant:read, menu:read, etc).
  2. 2

    Copier la clé

    Copiez la clé API générée. Assurez-vous de la stocker en sécurité. Vous ne pourrez plus la voir après avoir fermé le dialog.
  3. 3

    Faire des requêtes

    Utilisez la clé dans le header X-API-Key pour authentifier vos requêtes.
Sécurité

Authentification

Trois méthodes pour authentifier vos requêtes.

Méthode 1 : Header X-API-Key (Recommandé)

La méthode la plus simple et la plus sécurisée.

bash
curl -H "X-API-Key: qr_your_api_key_here" \
  https://api.couverty.ch/api/public/v1/restaurant

Méthode 2 : Authorization Bearer

Alternative utilisant le header Authorization standard.

bash
curl -H "Authorization: Bearer qr_your_api_key_here" \
  https://api.couverty.ch/api/public/v1/restaurant

Méthode 3 : Paramètre de requête (3CX uniquement)

Uniquement pour les intégrations 3CX qui ne peuvent pas utiliser les headers.

bash
curl https://api.couverty.ch/api/integrations/3cx/lookup?apikey=qr_your_api_key_here&phone=%2B41...

Sécurité

Vos clés API sont secrètes. Ne les exposez jamais côté client (navigateur). Stockez-les dans les variables d'environnement côté serveur. Si une clé est compromis, régénérez-la immédiatement dans vos paramètres.

Permissions

Chaque clé API a des permissions configurables: restaurant:read, menu:read, etc. Les requêtes échoueront si votre clé n'a pas la permission requise.
Authentifiés

Endpoints API v1

Accédez aux données de votre restaurant avec authentification par clé API.

GET /api/public/v1/restaurant

Récupère les informations du restaurant (nom, contact, horaires, branding).

GET/api/public/v1/restaurant
Permission :restaurant:read
Authentification :X-API-Key required
Exemple de réponse
json
{
  "success": true,
  "data": {
    "name": "Le Restaurant",
    "slug": "le-restaurant",
    "contact": {
      "email": "contact@example.com",
      "telephone": "+41 22 123 45 67",
      "address": {
        "rue": "10 Rue de la Paix",
        "npaVille": "1200 Genève",
        "pays": "Suisse"
      }
    },
    "hours": {
      "midi": {
        "enabled": true,
        "ouverture": "11:30",
        "fermeture": "14:30",
        "jours": [1, 2, 3, 4, 5]
      },
      "soir": {
        "enabled": true,
        "ouverture": "18:30",
        "fermeture": "23:00",
        "jours": [0, 1, 2, 3, 4, 5, 6]
      }
    },
    "social": {
      "website": "https://example.com",
      "facebook": "https://facebook.com/restaurant",
      "instagram": "https://instagram.com/restaurant",
      "tiktok": null,
      "googleReview": null,
      "tripadvisor": null
    },
    "branding": {
      "primaryColor": "#B91C1C",
      "secondaryColor": "#D4AF37",
      "logoUrl": "https://example.com/logo.png",
      "coverImageUrl": "https://example.com/cover.png"
    }
  },
  "meta": {
    "tenantId": "tenant_123",
    "fetchedAt": "2026-03-13T10:30:00Z"
  }
}

GET /api/public/v1/menu

Récupère le menu complet (plats et boissons) avec catégories et menu de la semaine.

GET/api/public/v1/menu
Permission :menu:read
Paramètres de requête :
  • type : all | plats | boissons (défaut: all)
  • includeHidden : true | false (défaut: false)
Exemple de réponse
json
{
  "success": true,
  "data": {
    "plats": {
      "categories": [
        {
          "id": "cat_123",
          "nom": "Entrées",
          "description": null,
          "plats": [
            {
              "id": "plat_456",
              "nom": "Salade César",
              "description": "Salade fraîche avec croutons",
              "prix": 18.50,
              "imageUrl": "https://example.com/salade.jpg",
              "allergenes": ["gluten", "oeuf"],
              "vegetarien": true,
              "vegan": false,
              "sansGluten": false
            }
          ]
        }
      ],
      "totalPlats": 45,
      "totalCategories": 5
    },
    "boissons": {
      "categories": [
        {
          "id": "cat_789",
          "nom": "Vins rouges",
          "description": "Sélection de vins rouges",
          "boissons": [
            {
              "id": "boi_321",
              "nom": "Côtes du Rhône",
              "description": "AOC 2020",
              "prix": 35.00,
              "volume": "75cl",
              "region": "Rhône",
              "annee": 2020
            }
          ]
        }
      ],
      "totalBoissons": 30,
      "totalCategories": 4
    },
    "menuSemaine": {
      "config": { ... },
      "menus": [ ... ]
    }
  },
  "meta": {
    "tenantId": "tenant_123",
    "fetchedAt": "2026-03-13T10:30:00Z"
  }
}
Public

Endpoints publics par slug

Accédez à la disponibilité, configuration et menu sans authentification. Utilisés par le widget.

Disponibilité générale

Ces endpoints ne nécessitent pas d'authentification. Le slug du restaurant est visible dans l'URL de votre page de réservation : https://restaurant.qr-menu.ch/book/[slug]

Configuration & Paramètres

GET/api/public/[slug]/config

Configuration restaurant pour le widget (horaires, créneaux, capacités). Cache : 5 min CDN, 1 min navigateur.

Champs retournés

horairesActifs, serviceMidiActif, serviceSoirActif

creneauxMidiConfig, creneauxSoirConfig

modeCapacite, capaciteMidi, capaciteSoir

joursOuvertsMidi, joursOuvertsSoir

Et 40+ autres champs (voir réponse complète)

GET/api/public/[slug]/settings

Paramètres publics du restaurant (nom, contact, couleurs, réseaux sociaux). Cache : 5 min CDN, 1 min navigateur.

Disponibilité

GET/api/public/[slug]/availability

Vérifie si une date/service/heure est disponible. Cache : 2 min.

Paramètres :
  • date : YYYY-MM-DD (requis)
  • service : midi | soir (requis)
  • heure : HH:mm (optionnel)
  • personnes : nombre (défaut: 2)
GET/api/public/[slug]/creneaux

Liste les créneaux horaires disponibles avec info de capacité. Cache : 1 min.

Paramètres :
  • date : YYYY-MM-DD (requis)
  • service : midi | soir (requis)
  • personnes ounombrePersonnes : nombre (défaut: 2)

Menu & Boissons

GET/api/public/[slug]/menu

Menu complet avec catégories et plats visibles. Cache : 10 min.

GET/api/public/[slug]/boissons

Carte des boissons avec catégories. Cache : 10 min.

GET/api/public/[slug]/fermetures

Jours de fermeture à venir (vacances, événements privés). Cache : 10 min.

Réservations

POST/api/public/[slug]/reservations

Crée une nouvelle réservation. Rate limit : 20 req/min par IP.

Corps de la requête :
  • prenom : string (requis)
  • nom : string (requis)
  • email : string (requis)
  • telephone : string (requis)
  • dateReservation : YYYY-MM-DD (requis)
  • service : midi | soir (requis)
  • nombrePersonnes : number (requis)
  • heureReservation : HH:mm (optionnel)
  • commentaires : string (optionnel)
Exemple de réponse
json
{
  "success": true,
  "data": {
    "id": "res_123abc",
    "prenom": "Jean",
    "nom": "Dupont",
    "email": "jean@example.com",
    "telephone": "+41 79 123 45 67",
    "dateReservation": "2026-03-20",
    "service": "soir",
    "nombrePersonnes": 4,
    "heureReservation": "19:30",
    "statut": "PENDING",
    "createdAt": "2026-03-13T10:30:00Z"
  }
}
Téléphonie

Intégration 3CX

Récupérez les données client et rapportez les appels.

Configuration requise

Pour utiliser l'API 3CX, vous devez d'abord créer une clé API avec les permissions 3cx:lookup et3cx:report.
GET/api/integrations/3cx/lookup

Recherche un client par numéro de téléphone. Retourne les informations et enrichissement (visites, no-shows).

Paramètres :
  • phone : string au format E.164 (requis) ex: +41791234567
Authentification :X-API-Key ou Authorization: Bearer
POST/api/integrations/3cx/report-call

Rapporte un appel (entrant, sortant, manqué). Crée une notification si appel manqué.

Corps de la requête :
  • phoneNumber : string E.164 (requis)
  • callType : Inbound | Outbound | Missed | Notanswered (requis)
  • durationSeconds : number (optionnel)
  • callDateTime : ISO 8601 (optionnel)
  • agent : string (optionnel)
Structures

Format des réponses

Toutes les réponses API suivent un format standardisé.

Réponse réussie (2xx)

json
{
  "success": true,
  "data": {
    // Les données demandées
  },
  "meta": {
    "tenantId": "tenant_123",
    "fetchedAt": "2026-03-13T10:30:00Z"
  }
}

Réponse d'erreur

json
{
  "success": false,
  "error": "Message d'erreur descriptif"
}
Gestion

Erreurs & Limites

Codes d'erreur, rate limits et troubleshooting.

Codes d'erreur HTTP

CodeSignificationExemple
200OK - Requête réussieDonnées retournées
400Bad Request - Paramètres invalidesDate manquante
401Unauthorized - Clé API manquante/invalideAPI key expiré
403Forbidden - Permission insuffisantemenu:read manquant
404Not Found - Ressource inexistanteRestaurant introuvable
429Too Many Requests - Rate limit atteintTrop de requêtes/min
500Internal Server ErrorErreur serveur

Rate limits

API v1

1000 requêtes par heure par clé API

Endpoints publics

Pas de limite stricte, utilise le cache CDN (5-10 min)

POST Réservations

20 requêtes par minute par adresse IP

3CX

1000 requêtes par heure par clé API

En-têtes de cache

Les endpoints publics incluent les en-têtes Cache-Control pour optimiser la performance :

http
Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=60

- max-age: Cache navigateur (en secondes)
- s-maxage: Cache CDN (en secondes)
- stale-while-revalidate: Servir ancien contenu pendant revalidation

Troubleshooting

401 Unauthorized - API key is required

Assurez-vous que :

  • Vous avez créé une clé API dans vos paramètres
  • Vous envoyez la clé dans le header X-API-Key
  • La clé n'a pas expiré ou été révoquée
403 Forbidden - Missing required permission

La clé API n'a pas les permissions requises :

  • Régénérez la clé avec les bonnes permissions in vos paramètres
  • Vérifiez que l'endpoint ne nécessite pas d'authentification
429 Too Many Requests

Vous avez atteint le rate limit :

  • Attendez quelques secondes avant de réessayer
  • Implémentez un backoff exponentiel dans votre code
  • Utilisez le cache pour réduire le nombre de requêtes
CORS errors

Les endpoints publics ([slug]) supportent CORS pour le widget. Si vous avez des erreurs CORS :

  • Utilisez ces endpoints uniquement depuis le navigateur, pas depuis un serveur privé
  • Pour les appels serveur-à-serveur, utilisez les endpoints v1 avec clé API
Implémentation

Exemples de code

Exemples complets dans plusieurs langages pour commencer rapidement.

Récupérer les infos du restaurant

javascript
const API_KEY = process.env.COUVERTY_API_KEY;
const API_BASE = 'https://api.couverty.ch';

async function getRestaurantInfo() {
  try {
    const response = await fetch(`${API_BASE}/api/public/v1/restaurant`, {
      headers: {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json',
      },
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const result = await response.json();

    if (!result.success) {
      throw new Error(result.error);
    }

    console.log('Restaurant:', result.data);
    return result.data;
  } catch (error) {
    console.error('Erreur:', error.message);
    throw error;
  }
}

async function getMenu() {
  try {
    const response = await fetch(
      `${API_BASE}/api/public/v1/menu?type=plats&includeHidden=false`,
      {
        headers: { 'X-API-Key': API_KEY },
      }
    );

    if (!response.ok) throw new Error(`HTTP ${response.status}`);

    const result = await response.json();
    return result.data;
  } catch (error) {
    console.error('Erreur:', error.message);
    throw error;
  }
}

// Utilisation
(async () => {
  const restaurant = await getRestaurantInfo();
  const menu = await getMenu();
})();

Besoin d'aide ?

Consultez notre documentation ou contactez le support.

Gérer les clés API