5 tips voor een rotsvaste API

Elke zichzelf respecterende online dienst heeft tegenwoordig een API om het mogelijk te maken verder te bouwen op de dienst. In februari 2009 lanceerden we bij Moneybird een API om de gegevens in een account te kunnen benaderen. In dit weblog artikel willen we graag laten zien hoe de API zich in de afgelopen jaren ontwikkeld heeft.

1) Bepaal acties en attributen

De eerste stap bij het opzetten van een API is bepalen welke acties een gebruiker via de API mag aanroepen en welke informatie je wilt aanbieden. We maken bij Moneybird gebruik van het Rails framework, hierin is een duidelijke scheiding tussen acties in controllers en serializatie van informatie in de modellen.

Om te bepalen welke acties een gebruiker mag aanroepen, kun je aangeven welke acties van een controller reageren op JSON of XML. Als je bepaalde acties niet ondersteunt kun je het beste een ‘not implemented’ reactie teruggeven:

def index
  @invoice = Invoice.find(params[:id])

  respond_to do |wants|
    wants.html
    wants.xml  { render :xml => @invoice }
    wants.json { head :not_implemented }
  end
end

In het model kun je bij de serializatie aangeven welke attributen en methoden teruggegeven moeten worden. Niet alle attributen in een model zul je aan de buitenwereld willen laten zien. In Moneybird gebruiken we een serialize_for_version methode om te definieren welke attributen voor welke versie van de API beschikbaar zijn:

serialize_for_version 1.0 do
  methods :contact_name, :name, :revision
  only    :address, :city, :company_name, :country, :email, :firstname, :lastname
end

2) Authenticatie

Door middel van authenticatie weet je wie toegang tot je systeem wil en tot welke informatie die persoon toegang heeft. De simpelste manier om authenticatie voor een API op te lossen is door middel van HTTP basic authentication. De gebruiker van je API zal in zijn code een gebruikersnaam en wachtwoord op moeten nemen waarmee hij verbinding mag maken. Deze methode werkt prima voor eenvoudige API koppelingen.

Wanneer externe partij je API gaan implementeren en aanbieden naar meer gebruikers, moet je je realiseren dat zij voor elke gebruiker een gebruikersnaam en wachtwoord moeten opslaan. Om dit te voorkomen kun je oauth gebruiken. Via een uitwisseling van tokens en goedkeuring van de gebruiker krijgt de externe applicatie toegang tot de API zonder een gebruikersnaam en wachtwoord te hoeven weten, je zult deze werkwijze herkennen van Twitter en Facebook Het grote voordeel is ook dat je een toegang altijd kunt intrekken door de tokens ongeldig te maken.

In Moneybird gebruiken we Warden voor authenticatie op middleware niveau. Voor oauth hebben we een speciale provider als strategy geschreven: warden_oauth_provider

3) Synchronisatie

Bij de eerste opzet van je API, zul je waarschijnlijk niet gelijk te maken hebben met grote hoeveelheden gegevens. Toen we onze API gingen gebruiken voor het bouwen van onze iPhone applicatie, kwamen we tot de ontdekking dat dit heel andere eisen stelt aan een API. Een iPhone kan niet 1000 facturen in XML laden en parsen zonder dat de gebruiker hier last van heeft.

Een oplossing voor grote hoeveelheden data is een synchronisatie API. Bij het opvragen van informatie geef je aan elke informatie je reeds hebt. De API zal teruggeven welke informatie nieuw of gewijzigd is. Vervolgens kun je op basis van die informatie in stukjes de data via XML opvragen. Een voorbeeld hiervan kun je vinden in de API documentatie op onze website

4) Versioning & testing

Het is ons al een paar keer overkomen dat een kleine wijziging in de API, grote gevolgen had in applicaties die tegen de API aanpraten. Een API mag niet zomaar veranderen, maar dit mag ook de ontwikkeling van je web applicatie niet in de weg staan. Een manier om dit op te lossen is om je API een versienummer mee te geven.

Je kunt dit versienummer bijvoorbeeld meegeven in de URL: ‘/api/v1.0/invoices.xml’. Op basis van het versienummer bepaal je welke informatie teruggegeven moet worden en kun je backwardscompatibility garanderen. Door te testen kun je vastleggen dat de API nooit zomaar mag wijzigen.

Zorg ervoor dat je je API goed test in een test suite. Wij gebruiken hiervoor Cucumber, die requests naar de server doet en controleert of het resultaat correct is. Een nieuwe versie van de API zit in nieuwe tests, hierdoor kun je altijd de legacy versies blijven ondersteunen.

Feature: API contact test v1.0

  Background:
    Given pietje is a valid API user for bluetools
    And I send and accept XML

  Scenario: GET request /api/v1.0/contacts/123.xml and validate response
  When I have inserted a valid contact
   And I send a GET request to "/api/v1.0/contacts/123.xml"
  Then the response should contain http status code 200
   And the response should contain 23 "/contact/" elements
   And the response should contain an element "/contact/address1" with value "address1"

5) Throttling

Wanneer je de API netjes op orde hebt, zullen ook de eerste gebruikers van je API binnen komen. Onze ervaring is dat het soms wat tijd kost om een API goed te begrijpen. Door een kleine fout in een implementatie kunnen 10 API request plots 1000 requests worden. Het is belangrijk om het effect hiervan op je servers te bestuderen.

Bij Moneybird hebben we ervoor gekozen om een limiet te stellen aan het aantal API requests per uur. Op deze manier beschermen we onze servers tegen ongelukkige implementaties van onze API gebruikers en zit de API onze normale gebruikers niet in de weg.

Er komt meer kijken bij het opzetten van een goede API dan wij in het begin gedacht hadden. Toch heeft de API ons ook veel mooie dingen gebracht, daarom raden we iedereen aan om een API aan te bieden in zijn web applicatie. Zorg ervoor dat je nadenkt over de bovenstaande tips, maar vergeet vooral niet: een goede API staat of valt bij goede documentatie!

Deel dit artikel op je favoriete social netwerk