API KVK avec Go : données d'entreprises néerlandaises
KVKBase Team

API KVK avec Go : données d'entreprises néerlandaises

Intégrez l'API KVKBase dans votre projet Go : clients HTTP, structs, gestion des erreurs et bibliothèque cliente réutilisable, pour débutants comme confirmés.

kvkapigolanggodéveloppeursintégration

Go est l’un des langages de programmation dont la popularité croît le plus vite pour les services backend, les microservices et les outils en ligne de commande. Sa combinaison de hautes performances, de concurrence simple et d’une bibliothèque standard puissante en fait un choix prisé des équipes qui construisent des intégrations d’API fiables. Dans ce guide, nous vous montrons comment intégrer l’API KVKBase à votre projet Go pour interroger les données d’entreprises néerlandaises.

Pourquoi Go pour les intégrations KVK ?

Go dispose d’un excellent client HTTP intégré, d’une bonne prise en charge du JSON et d’un typage strict via les structs. Il est donc idéal pour les intégrations d’API où vous devez :

  • Valider rapidement des numéros KVK lors de l’inscription d’un client
  • Récupérer des données d’entreprise pour votre CRM ou votre ERP
  • Traiter par lots de longues listes de numéros KVK
  • Construire un microservice ou un outil interne qui a besoin de données d’entreprise

L’API KVKBase renvoie du JSON structuré, qui s’associe sans effort au paquet encoding/json de Go et aux définitions de structs.

Prérequis

  • Go 1.21 ou supérieur
  • Une clé d’API KVKBase
  • Aucune dépendance externe : uniquement la bibliothèque standard de Go

Étape 1 : définir vos structs

Commencez par définir des structs qui représentent la réponse de l’API. La désérialisation JSON de Go fonctionne au mieux lorsque vous ajoutez des tags de struct correspondant aux noms des champs JSON.

// kvkbase/types.go

package kvkbase

type Address struct {
	Street      string `json:"straat"`
	HouseNumber string `json:"huisnummer"`
	PostalCode  string `json:"postcode"`
	City        string `json:"plaats"`
	Country     string `json:"land"`
}

type SbiCode struct {
	Code        string `json:"code"`
	Description string `json:"omschrijving"`
}

type Company struct {
	KvkNumber   string    `json:"kvkNummer"`
	Name        string    `json:"naam"`
	LegalForm   string    `json:"rechtsvorm"`
	Active      bool      `json:"actief"`
	Address     Address   `json:"adres"`
	SbiCodes    []SbiCode `json:"sbiCodes"`
	VatNumber   string    `json:"btwNummer,omitempty"`
}

type APIResponse struct {
	Success bool     `json:"succes"`
	Data    *Company `json:"data,omitempty"`
	Error   string   `json:"fout,omitempty"`
}

Étape 2 : construire un client réutilisable

Créez une struct cliente qui gère votre clé d’API et votre client HTTP. C’est l’approche idiomatique en Go : l’injection de dépendances plutôt que les variables globales.

// kvkbase/client.go

package kvkbase

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"
)

const baseURL = "https://api.kvkbase.nl/api/v1"

type Client struct {
	apiKey     string
	httpClient *http.Client
}

func NewClient(apiKey string) *Client {
	return &Client{
		apiKey: apiKey,
		httpClient: &http.Client{
			Timeout: 10 * time.Second,
		},
	}
}

func (c *Client) GetCompany(kvkNumber string) (*Company, error) {
	url := fmt.Sprintf("%s/kvk/%s", baseURL, kvkNumber)

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}
	req.Header.Set("x-api-key", c.apiKey)
	req.Header.Set("Accept", "application/json")

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("API call failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode == 404 {
		return nil, fmt.Errorf("KVK number %s not found", kvkNumber)
	}
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
	}

	var result APIResponse
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("JSON decode failed: %w", err)
	}

	if !result.Success || result.Data == nil {
		return nil, fmt.Errorf("API error: %s", result.Error)
	}

	return result.Data, nil
}

Étape 3 : utilisation de base

// main.go

package main

import (
	"fmt"
	"log"
	"os"

	"yourproject/kvkbase"
)

func main() {
	apiKey := os.Getenv("KVKBASE_API_KEY")
	if apiKey == "" {
		log.Fatal("KVKBASE_API_KEY environment variable not set")
	}

	client := kvkbase.NewClient(apiKey)

	company, err := client.GetCompany("12345678")
	if err != nil {
		log.Fatalf("Error: %v", err)
	}

	fmt.Printf("Company name: %s\n", company.Name)
	fmt.Printf("KVK number:  %s\n", company.KvkNumber)
	fmt.Printf("Legal form:  %s\n", company.LegalForm)
	fmt.Printf("Active:      %v\n", company.Active)
	fmt.Printf("Address:     %s %s, %s %s\n",
		company.Address.Street,
		company.Address.HouseNumber,
		company.Address.PostalCode,
		company.Address.City,
	)
}

Étape 4 : recherches par lots concurrentes avec les goroutines

L’une des plus grandes forces de Go est la concurrence via les goroutines. C’est particulièrement utile lorsque vous devez traiter une liste de numéros KVK sans attendre que chaque requête se termine séquentiellement.

// batch.go

package kvkbase

import (
	"sync"
)

type BatchResult struct {
	KvkNumber string
	Company   *Company
	Err       error
}

func (c *Client) BulkLookup(kvkNumbers []string, maxConcurrent int) []BatchResult {
	results := make([]BatchResult, len(kvkNumbers))
	sem := make(chan struct{}, maxConcurrent) // sémaphore pour limiter le débit
	var wg sync.WaitGroup

	for i, kvk := range kvkNumbers {
		wg.Add(1)
		go func(idx int, number string) {
			defer wg.Done()
			sem <- struct{}{}        // acquérir un emplacement
			defer func() { <-sem }() // libérer l'emplacement

			company, err := c.GetCompany(number)
			results[idx] = BatchResult{
				KvkNumber: number,
				Company:   company,
				Err:       err,
			}
		}(i, kvk)
	}

	wg.Wait()
	return results
}

Réglez maxConcurrent pour ne pas atteindre les limites de débit de l’API. Une valeur de 5 à 10 est généralement sûre.

numbers := []string{"12345678", "87654321", "11223344"}
results := client.BulkLookup(numbers, 5)

for _, r := range results {
	if r.Err != nil {
		fmt.Printf("%s: ERROR - %v\n", r.KvkNumber, r.Err)
		continue
	}
	fmt.Printf("%s: %s (%s)\n", r.KvkNumber, r.Company.Name, r.Company.LegalForm)
}

Gestion des erreurs en Go

La gestion explicite des erreurs de Go rend les intégrations robustes. Le client utilise fmt.Errorf avec %w pour l’enveloppement des erreurs, ce qui préserve le contexte à mesure que les erreurs remontent :

company, err := client.GetCompany("00000000")
if err != nil {
	if strings.Contains(err.Error(), "not found") {
		// Le numéro KVK n'existe pas
		fmt.Println("Unknown KVK number")
	} else {
		// Erreur réseau ou serveur
		log.Printf("API error: %v", err)
	}
	return
}

Utilisation dans un gestionnaire HTTP (Echo / Gin / chi)

Si vous utilisez Go pour construire une API web, le schéma est le même. Voici un exemple avec le framework populaire chi :

// handlers/kvk.go

package handlers

import (
	"encoding/json"
	"net/http"

	"yourproject/kvkbase"
	"github.com/go-chi/chi/v5"
)

type KvkHandler struct {
	client *kvkbase.Client
}

func NewKvkHandler(client *kvkbase.Client) *KvkHandler {
	return &KvkHandler{client: client}
}

func (h *KvkHandler) GetCompany(w http.ResponseWriter, r *http.Request) {
	kvkNumber := chi.URLParam(r, "kvkNumber")

	company, err := h.client.GetCompany(kvkNumber)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadGateway)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(company)
}

Enregistrez le gestionnaire dans votre routeur :

r := chi.NewRouter()
kvkHandler := handlers.NewKvkHandler(kvkbase.NewClient(os.Getenv("KVKBASE_API_KEY")))
r.Get("/api/company/{kvkNumber}", kvkHandler.GetCompany)

Tests

Le paquet de test de Go est intégré. Utilisez un faux serveur HTTP pour tester votre client sans effectuer de vrais appels d’API :

// kvkbase/client_test.go

package kvkbase_test

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"yourproject/kvkbase"
)

func TestGetCompany(t *testing.T) {
	// Configurer le faux serveur
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		response := kvkbase.APIResponse{
			Success: true,
			Data: &kvkbase.Company{
				KvkNumber: "12345678",
				Name:      "Test BV",
				LegalForm: "BV",
				Active:    true,
			},
		}
		json.NewEncoder(w).Encode(response)
	}))
	defer server.Close()

	client := kvkbase.NewClient("test-key")

	company, err := client.GetCompany("12345678")
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}

	if company.Name != "Test BV" {
		t.Errorf("Expected 'Test BV', got '%s'", company.Name)
	}
}

Prochaines étapes

Avec cette base, vous pouvez aller dans toutes les directions :

Prêt à vous lancer ? Obtenez votre clé d’API sur kvkbase.nl.