Documentation API

Intégrez le puissant moteur de tarification de Grula dans vos applications avec notre API REST complète. Calculez les prix, gérez les politiques tarifaires et configurez les ajustements dynamiques par programmation.

Démarrage rapide

Commencez avec l'API Grula en quelques minutes. Tout ce dont vous avez besoin est un token API pour commencer à faire des requêtes.

Authentification

Toutes les requêtes API nécessitent une authentification avec un token Bearer. Vous pouvez générer votre token API depuis le tableau de bord Grula.

Authorization: Bearer YOUR_API_TOKEN

URL de base

https://api.grula.net

Concepts clés

Politiques de tarification (grilles tarifaires)

Les politiques de tarification définissent vos prix de base pour les produits ou services. Pensez-y comme vos grilles tarifaires qui contiennent les règles de tarification fondamentales pour votre entreprise.

Politiques d'ajustement des prix (remises et frais)

Les politiques d'ajustement des prix modifient vos prix de base en appliquant des remises, des frais ou d'autres ajustements basés sur des conditions spécifiques comme le type de client, le volume ou les facteurs saisonniers.

Get PricePOST

Calculez un prix unique basé sur les facteurs de prix, la devise et la date de tarification optionnelle. C'est l'endpoint principal pour les calculs de prix en temps réel.

Endpoint

POST /api/v1/price
curl -X POST "https://api.grula.net/api/v1/price" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "environmentId": "123e4567-e89b-12d3-a456-426614174000",
    "priceDrivers": [
      {
        "name": "product",
        "value": "laptop"
      },
      {
        "name": "customer_tier",
        "value": "premium"
      }
    ],
    "currencyThreeLetterCode": "USD",
    "pricingDate": "2024-01-15T10:00:00Z"
  }'
import requests
    import json

    url = "https://api.grula.net/api/v1/price"
    headers = {
        "Authorization": "Bearer YOUR_API_TOKEN",
        "Content-Type": "application/json"
    }

    payload = {
        "environmentId": "123e4567-e89b-12d3-a456-426614174000",
        "priceDrivers": [
            {
                "name": "product",
                "value": "laptop"
            },
            {
                "name": "customer_tier",
                "value": "premium"
            }
        ],
        "currencyThreeLetterCode": "USD",
        "pricingDate": "2024-01-15T10:00:00Z"
    }

    response = requests.post(url, headers=headers, json=payload)
    price_data = response.json()
    print(f"Price: {price_data['amount']['amount']} {price_data['amount']['currencyThreeLetterCode']}")
const axios = require('axios');

    const getPricing = async () => {
      try {
        const response = await axios.post('https://api.grula.net/api/v1/price', {
          environmentId: '123e4567-e89b-12d3-a456-426614174000',
          priceDrivers: [
            {
              name: 'product',
              value: 'laptop'
            },
            {
              name: 'customer_tier',
              value: 'premium'
            }
          ],
          currencyThreeLetterCode: 'USD',
          pricingDate: '2024-01-15T10:00:00Z'
        }, {
          headers: {
            'Authorization': 'Bearer YOUR_API_TOKEN',
            'Content-Type': 'application/json'
          }
        });
    
        console.log(`Price: ${response.data.amount.amount} ${response.data.amount.currencyThreeLetterCode}`);
        return response.data;
      } catch (error) {
        console.error('Error fetching price:', error.response?.data || error.message);
      }
    };

    getPricing();
using System;
    using System.Net.Http;
    using System.Text;
    using System.Text.Json;
    using System.Threading.Tasks;

    public class PricingClient
    {
        private readonly HttpClient _httpClient;
        private const string BaseUrl = "https://api.grula.net";

        public PricingClient(string apiToken)
        {
            _httpClient = new HttpClient();
            _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiToken}");
        }

        public async Task<PriceResponse> GetPriceAsync(PriceRequest request)
        {
            var json = JsonSerializer.Serialize(request);
            var content = new StringContent(json, Encoding.UTF8, "application/json");
        
            var response = await _httpClient.PostAsync($"{BaseUrl}/api/v1/price", content);
            response.EnsureSuccessStatusCode();
        
            var responseJson = await response.Content.ReadAsStringAsync();
            return JsonSerializer.Deserialize<PriceResponse>(responseJson);
        }
    }

    // Usage
    var client = new PricingClient("YOUR_API_TOKEN");
    var request = new PriceRequest
    {
        EnvironmentId = Guid.Parse("123e4567-e89b-12d3-a456-426614174000"),
        PriceDrivers = new[]
        {
            new PriceDriver { Name = "product", Value = "laptop" },
            new PriceDriver { Name = "customer_tier", Value = "premium" }
        },
        CurrencyThreeLetterCode = "USD",
        PricingDate = DateTime.Parse("2024-01-15T10:00:00Z")
    };

    var price = await client.GetPriceAsync(request);
    Console.WriteLine($"Price: {price.Amount.Amount} {price.Amount.CurrencyThreeLetterCode}");
import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    import java.net.URI;
    import java.time.Duration;
    import com.fasterxml.jackson.databind.ObjectMapper;

    public class PricingClient {
        private final HttpClient httpClient;
        private final ObjectMapper objectMapper;
        private final String apiToken;
        private static final String BASE_URL = "https://api.grula.net";

        public PricingClient(String apiToken) {
            this.httpClient = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(10))
                .build();
            this.objectMapper = new ObjectMapper();
            this.apiToken = apiToken;
        }

        public PriceResponse getPrice(PriceRequest request) throws Exception {
            String requestBody = objectMapper.writeValueAsString(request);
        
            HttpRequest httpRequest = HttpRequest.newBuilder()
                .uri(URI.create(BASE_URL + "/api/v1/price"))
                .header("Authorization", "Bearer " + apiToken)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                .build();

            HttpResponse<String> response = httpClient.send(httpRequest, 
                HttpResponse.BodyHandlers.ofString());
        
            if (response.statusCode() == 200) {
                return objectMapper.readValue(response.body(), PriceResponse.class);
            } else {
                throw new RuntimeException("API call failed: " + response.statusCode());
            }
        }
    }

    // Usage
    PricingClient client = new PricingClient("YOUR_API_TOKEN");
    PriceRequest request = new PriceRequest();
    request.setEnvironmentId(UUID.fromString("123e4567-e89b-12d3-a456-426614174000"));
    request.setPriceDrivers(Arrays.asList(
        new PriceDriver("product", "laptop"),
        new PriceDriver("customer_tier", "premium")
    ));
    request.setCurrencyThreeLetterCode("USD");
    request.setPricingDate(Instant.parse("2024-01-15T10:00:00Z"));

    PriceResponse price = client.getPrice(request);
    System.out.println("Price: " + price.getAmount().getAmount() + " " + 
        price.getAmount().getCurrencyThreeLetterCode());

Get Multiple PricesPOST

Calculez plusieurs prix en une seule requête. Efficace pour les opérations de tarification en masse avec un maximum de 100 requêtes de prix par appel.

Endpoint

POST /api/v1/prices
curl -X POST "https://api.grula.net/api/v1/prices" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "environmentId": "123e4567-e89b-12d3-a456-426614174000",
    "priceRequests": [
      {
        "priceDrivers": [
          {"name": "product", "value": "laptop"},
          {"name": "customer_tier", "value": "premium"}
        ],
        "currencyThreeLetterCode": "USD",
        "pricingDate": "2024-01-15T10:00:00Z"
      },
      {
        "priceDrivers": [
          {"name": "product", "value": "desktop"},
          {"name": "customer_tier", "value": "standard"}
        ],
        "currencyThreeLetterCode": "EUR",
        "pricingDate": "2024-01-15T10:00:00Z"
      }
    ]
  }'
import requests

    url = "https://api.grula.net/api/v1/prices"
    headers = {
        "Authorization": "Bearer YOUR_API_TOKEN",
        "Content-Type": "application/json"
    }

    payload = {
        "environmentId": "123e4567-e89b-12d3-a456-426614174000",
        "priceRequests": [
            {
                "priceDrivers": [
                    {"name": "product", "value": "laptop"},
                    {"name": "customer_tier", "value": "premium"}
                ],
                "currencyThreeLetterCode": "USD",
                "pricingDate": "2024-01-15T10:00:00Z"
            },
            {
                "priceDrivers": [
                    {"name": "product", "value": "desktop"},
                    {"name": "customer_tier", "value": "standard"}
                ],
                "currencyThreeLetterCode": "EUR",
                "pricingDate": "2024-01-15T10:00:00Z"
            }
        ]
    }

    response = requests.post(url, headers=headers, json=payload)
    prices = response.json()

    for i, price in enumerate(prices):
        print(f"Price {i+1}: {price['amount']['amount']} {price['amount']['currencyThreeLetterCode']}")
const axios = require('axios');

    const getBatchPrices = async () => {
      try {
        const response = await axios.post('https://api.grula.net/api/v1/prices', {
          environmentId: '123e4567-e89b-12d3-a456-426614174000',
          priceRequests: [
            {
              priceDrivers: [
                { name: 'product', value: 'laptop' },
                { name: 'customer_tier', value: 'premium' }
              ],
              currencyThreeLetterCode: 'USD',
              pricingDate: '2024-01-15T10:00:00Z'
            },
            {
              priceDrivers: [
                { name: 'product', value: 'desktop' },
                { name: 'customer_tier', value: 'standard' }
              ],
              currencyThreeLetterCode: 'EUR',
              pricingDate: '2024-01-15T10:00:00Z'
            }
          ]
        }, {
          headers: {
            'Authorization': 'Bearer YOUR_API_TOKEN',
            'Content-Type': 'application/json'
          }
        });
    
        response.data.forEach((price, index) => {
          console.log(`Price ${index + 1}: ${price.amount.amount} ${price.amount.currencyThreeLetterCode}`);
        });
    
        return response.data;
      } catch (error) {
        console.error('Error fetching batch prices:', error.response?.data || error.message);
      }
    };

    getBatchPrices();

Exemples de réponse

Comprendre la structure des réponses API vous aide à intégrer efficacement les données de tarification dans vos applications.

Price Response

{
  "amount": {
    "amount": 1299.99,
    "currencyThreeLetterCode": "USD"
  },
  "priceComponents": [
    {
      "pricingPolicyId": "123e4567-e89b-12d3-a456-426614174000",
      "amount": {
        "amount": 1499.99,
        "currencyThreeLetterCode": "USD"
      }
    },
    {
      "priceAdjustmentPolicyId": "456e7890-e89b-12d3-a456-426614174001",
      "amount": {
        "amount": -200.00,
        "currencyThreeLetterCode": "USD"
      },
      "priceAdjustmentPolicyActionName": "Premium Customer Discount",
      "priceAdjustmentPolicyValue": 0.15
    }
  ]
}

Gestion des erreurs

L'API utilise des codes de statut HTTP standard pour indiquer le succès ou l'échec des requêtes. Voici les codes de statut les plus courants que vous rencontrerez.

Codes de statut HTTP

200
Success - Requête terminée avec succès
201
Created - Ressource créée avec succès
400
Bad Request - Paramètres de requête invalides
401
Unauthorized - Token API invalide ou manquant
404
Not Found - Ressource non trouvée
409
Conflict - La ressource existe déjà ou incompatibilité de version
500
Internal Server Error - Une erreur est survenue côté serveur