REST API's bouwen voor externe integraties
Een API endpoint is een REST-interface waarmee externe systemen data kunnen ophalen uit of schrijven naar je database. SQLio ondersteunt de vier standaard HTTP-methoden: GET (ophalen), POST (aanmaken), PATCH (bijwerken) en DELETE (verwijderen).
Elk endpoint krijgt automatisch een URL en wordt gedocumenteerd in de Swagger/OpenAPI omgeving. Externe systemen kunnen de API aanroepen met een API key en Basic authenticatie.
Instructievideo: GET-endpoint op de dataset Verkooporders, API-gebruiker met sleutel en rechten, en de aanroep in Swagger.
Klik in het menu op API configuratie. Je ziet een overzicht van alle bestaande endpoints, gegroepeerd per tag.
Bovenaan verschijnt een formulier. Een nieuw endpoint staat standaard op Inactief; zet de status aan als het aangeroepen mag worden.
| Veld | Verplicht | Toelichting |
|---|---|---|
| API Naam | Ja | Naam zonder spaties — wordt onderdeel van de URL. Bijvoorbeeld: GetCustomers |
| Omschrijving | Nee | Beschrijving van wat het endpoint doet |
| Tag / Groep | Nee | Groepering in Swagger documentatie (bijv. "Klanten", "Orders") |
| Status | Nee | Actief/Inactief toggle |
| Type | Nee | Intern (verborgen in Swagger) of Extern (zichtbaar in Swagger) |
De URL wordt automatisch opgebouwd uit de URL-prefix van de omgeving, de subprefix van de databron (connectie-alias) en de naam: /api/[omgeving]/[databron]/{ApiNaam}.
| Databron | Test | Productie |
|---|---|---|
nl (geen subprefix) |
/api/test/verkooporders |
/api/verkooporders |
be (subprefix be) |
/api/test/be/verkooporders |
/api/be/verkooporders |
Dezelfde naam mag bestaan met verschillende HTTP-methodes (bijv. GET en POST op orders).
verkooporders op de dataset Verkooporders.| Veld | Opties | Toelichting |
|---|---|---|
| HTTP Method | GET, POST, PATCH, DELETE | Bepaalt het type operatie |
| Execution Type | Table of Stored Procedure | Bepaalt de uitvoeringsbron (bij POST/PATCH/DELETE) |
| Response Dataset | Dropdown | Optioneel: dataset die de response levert na uitvoering |
| HTTP Status | 200 OK, 201 Created, 204 No Content | De statuscode bij succes (bij POST/PATCH) |
Bij opslaan vraagt SQLio om een versie en een notitie. Daarna verschijnt de kaart Bereikbaar via databronnen: vink aan via welke connectie-aliassen het endpoint bereikbaar is. Je ziet direct de URL per databron. Alleen databronnen waarop de dataset mag draaien zijn te kiezen.
nl en via be.Een GET endpoint haalt data op uit de database via een gekoppelde dataset.
De dataset wordt uitgevoerd met eventuele query parameters als filters:
GET /api/GetCustomers?status=actief&city=Amsterdam
De parameters status en city worden doorgegeven aan de dataset WHERE-condities. Het resultaat is de JSON-output van de dataset.
[
{
"klantnummer": "K001",
"naam": "ACME Corp",
"stad": "Amsterdam",
"status": "actief"
},
{
"klantnummer": "K002",
"naam": "Widgets BV",
"stad": "Amsterdam",
"status": "actief"
}
]
Een POST endpoint maakt nieuwe records aan in de database. De data wordt meegegeven als JSON body.
SQLio genereert automatisch de INSERT-query. Identity-kolommen en auto-gegenereerde velden (zoals CreatedAt) worden automatisch uitgesloten van de body.
EXEC dbo.sp_InsertOrder
@CustomerNo = :CustomerNo,
@Description = :Description,
@UserCode = N'SYSTEM'
:parameterNaam voor waarden uit de JSON body. Gebruik vaste waarden (zoals N'SYSTEM', 0, 'tekst') voor hardcoded parameters.
Bij een POST worden de parameters als body parameters behandeld. De Swagger documentatie toont ze als JSON request body.
Per parameter kun je instellen:
| Veld | Toelichting |
|---|---|
| Naam | Parameternaam (moet overeenkomen met de :parameter in het Execution Statement) |
| Type | Datatype (String, Integer, Long, GUID, Decimal, Boolean, DateTime) |
| Required | Of de parameter verplicht is |
| Beschrijving | Optionele beschrijving voor de Swagger documentatie |
Bij een Stored Procedure toont SQLio automatisch een Parameter Mapping sectie:
POST /api/CreateOrder
Content-Type: application/json
{
"CustomerNo": "K001",
"Description": "Nieuwe bestelling Q1"
}
Als je een Response Dataset hebt gekoppeld, worden de resultaten van de INSERT/SP gebruikt als parameters voor de dataset. Zo kun je na het aanmaken direct het volledige record terugsturen:
{
"orderId": 100,
"customerNo": "K001",
"description": "Nieuwe bestelling Q1",
"orderDate": "2024-01-15",
"status": "Nieuw"
}
Een PATCH endpoint werkt een bestaand record bij. De identifier gaat via de URL en de te wijzigen data via de JSON body.
EXEC dbo.sp_UpdateCustomer
@CustomerId = :customerId,
@Name = :name,
@Email = :email
customerId)Bij PATCH (en DELETE) worden URL parameters in het pad opgenomen:
PATCH /api/UpdateCustomer/123
De parameter 123 wordt gekoppeld aan customerId. In de Swagger documentatie verschijnen deze als path parameters.
De body bevat alleen de te wijzigen velden:
{
"name": "Nieuwe naam",
"email": "nieuw@email.nl"
}
SQLio genereert automatisch:
UPDATE [dbo].[Customers] SET Name = @body_Name, Email = @body_Email WHERE CustomerId = @url_CustomerId
Een DELETE endpoint verwijdert een record op basis van de identifier in de URL.
DELETE /api/DeleteCustomer/123
| Status | Betekenis |
|---|---|
| 204 No Content | Record succesvol verwijderd |
| 404 Not Found | Record niet gevonden |
| 409 Conflict | Record kan niet verwijderd worden (referentiële integriteit) |
Voor GET endpoints met grote datasets kun je cursor-based paginering inschakelen.
orderNr.Eerste pagina (zonder cursor):
GET /api/test/verkooporders
Response:
{
"data": [
{ "customerId": 1, "name": "ACME Corp" },
{ "customerId": 2, "name": "Widgets BV" },
...
],
"pageSize": 50,
"hasMore": true,
"after": "50",
"totalCount": 1250
}
Volgende pagina (met cursor):
GET /api/test/verkooporders?after=350202
De paginagrootte komt uit de configuratie van het endpoint; de aanroeper geeft alleen after mee. totalCount staat alleen in het antwoord als Totaal tonen aan staat. Child layers (bijvoorbeeld regels en klant) worden per record meegeleverd, net als zonder paginering.
Het veld after bevat de cursor-waarde van het laatste record. Bij meerdere cursor-kolommen worden de waarden gescheiden met een pipe: 123|2024-01-15.
Elke API-aanroep vereist twee vormen van authenticatie:
Authorization: Basic base64(gebruikersnaam:wachtwoord)
De gebruiker wordt aangemaakt in API gebruikersbeheer: gebruikersnaam, e-mail, volledige naam, bedrijf en wachtwoord (zelf invullen of laten genereren).
portaal-demo.X-API-Key: ak_64hexadecimaletekens
De API key wordt gegenereerd per gebruiker per omgeving, via de knop Keys bij de gebruiker. Kopieer de sleutel direct: SQLio toont hem maar één keer.
Per gebruiker kun je:
| Actie | Toelichting |
|---|---|
| API Key aanmaken | Genereer een nieuwe key met optionele naam |
| Vervaldatum instellen | Optioneel: key verloopt op een bepaalde datum |
| Deactiveren | Key tijdelijk uitschakelen |
| Verwijderen | Key permanent verwijderen |
Niet elke gebruiker heeft toegang tot elk endpoint. Via de knop Rechten bij de gebruiker vink je per omgeving aan welke endpoints hij mag aanroepen. De endpoints zijn gegroepeerd per tag; met het vinkje in de kop selecteer je de hele groep.
verkooporders in de omgeving Test.SQLio genereert automatisch Swagger/OpenAPI documentatie voor alle actieve, externe endpoints.
Ga naar /api-docs (of klik op Swagger Documentatie in API configuratie). Je logt eerst in met een API-gebruiker op de loginpagina /api-login.
Er is een aparte definitie per omgeving en databron, bijvoorbeeld Test APIs en Test (be) APIs. Kies de definitie rechtsboven.
Met de knop Swagger Instellingen in API configuratie pas je de Swagger-pagina aan:
| Instelling | Toelichting |
|---|---|
| API Titel | Titel bovenaan de Swagger pagina |
| Versie | API versie (bijv. "v1") |
| Beschrijving | Algemene informatie over je API |
| Contact naam | Naam van de contactpersoon |
| Contact e-mail | E-mailadres voor ondersteuning |
| Support URL | Link naar supportpagina |
| Bedrijfslogo | Logo op de API loginpagina (PNG/JPEG, max 500KB) |
In het API overzicht worden per endpoint statistieken bijgehouden:
| Kolom | Toelichting |
|---|---|
| Aantal calls | Totaal aantal keren dat het endpoint is aangeroepen |
| Laatste call | Datum en tijd van de laatste aanroep |
| Code | Betekenis | Wanneer |
|---|---|---|
| 200 OK | Verzoek geslaagd | GET met data, POST/PATCH met response |
| 201 Created | Record aangemaakt | POST (indien geconfigureerd) |
| 204 No Content | Uitgevoerd zonder response | DELETE, POST/PATCH zonder response dataset |
| Code | Betekenis | Wanneer |
|---|---|---|
| 400 Bad Request | Ongeldige invoer | Ontbrekende parameters, verkeerd type, SP fout (state 1-10) |
| 401 Unauthorized | Niet geautoriseerd | Ontbrekende of ongeldige Basic Auth of API Key |
| 403 Forbidden | Geen toegang | Gebruiker heeft geen permissie voor dit endpoint |
| 404 Not Found | Niet gevonden | Endpoint bestaat niet, of record niet gevonden (SP state 20) |
| 405 Method Not Allowed | Verkeerde methode | GET request naar een POST endpoint, etc. |
| 409 Conflict | Conflict | Duplicate key of foreign key constraint |
| Code | Betekenis | Wanneer |
|---|---|---|
| 500 Internal Server Error | Interne fout | Onverwachte exceptie |
| 503 Service Unavailable | Niet beschikbaar | Licentie verlopen of dataset/omgeving inactief |
Je kunt vanuit een stored procedure specifieke HTTP status codes retourneren via RAISERROR:
-- 400 Bad Request (state 1, 2 of 10)
RAISERROR('Klantnummer is verplicht', 16, 1)
-- 404 Not Found (state 20)
RAISERROR('Klant niet gevonden', 16, 20)
De State parameter bepaalt welke HTTP status code wordt teruggestuurd.
GET /api/GetCustomers?pageSize=50
:customerId)GET /api/GetCustomer?customerId=K001
POST /api/CreateCustomer
Content-Type: application/json
{
"Name": "Nieuw Bedrijf BV",
"City": "Rotterdam",
"Email": "info@nieuwbedrijf.nl"
}
Response:
{
"customerId": "K042",
"name": "Nieuw Bedrijf BV",
"city": "Rotterdam",
"email": "info@nieuwbedrijf.nl",
"createdAt": "2024-01-15T10:30:00"
}
PATCH /api/UpdateCustomer/K042
Content-Type: application/json
{
"City": "Amsterdam",
"Email": "nieuw@nieuwbedrijf.nl"
}
DELETE /api/DeleteCustomer/K042
| Probleem | Oorzaak | Oplossing |
|---|---|---|
| 401 Unauthorized | Basic Auth of API Key ontbreekt/onjuist | Controleer beide authenticatie-headers |
| 403 Forbidden | Gebruiker heeft geen permissie | Controleer endpoint-permissies in gebruikersbeheer |
| 404 Not Found | Endpoint naam klopt niet of omgeving-prefix ontbreekt | Controleer de URL (bijv. /api/test/... voor testomgeving) |
| Endpoint niet zichtbaar in Swagger | Type staat op "Intern" | Wijzig type naar "Extern" |
| Parameters verschijnen niet in Swagger | Parameters niet geconfigureerd | Voeg parameters toe in de endpoint configuratie |
| POST retourneert leeg object | Geen Response Dataset gekoppeld | Koppel een dataset die het aangemaakte record teruggeeft |
| SP parameter wordt niet doorgegeven | Parameternaam komt niet overeen | Zorg dat de body parameter exact overeenkomt met de :parameter in het Execution Statement |
| Hardcoded SP waarde ontbreekt | Syntax onjuist | Gebruik het formaat @Param = N'waarde' of @Param = 123 |
| "Licentie verlopen" | Licentie is verlopen | Vernieuw de licentie |
| Trage response bij grote datasets | Geen paginering of te brede filters | Schakel paginering in of voeg WHERE-condities toe aan de dataset |