API

Dette kapitel er henvendt til udviklere, og kræver erfaring med programmering.

En rækkke funktioner i ForeningLet er udstillet via et API. Dermed er det muligt at lave integrationer op mod ForeningLet fra andre systemer. I det følgende benævnes “andre systemer” som klient.

Læs indholdet af dette kapitel omhyggeligt, herunder begrænsninger og ansvar som beskrevet nedenfor, for at forstå generelle restriktioner.

Hvis ForeningLet vurderer, at I har eller har forsøgt at overtræde betingelserne for brugen af API’et, kan jeres adgang til at bruge API’et blive midlertidigt eller permanent tilbagekaldt.

Sikkerhed og autentifikation

For at få lov til at tilgå API’et, skal klienten som ønsker at integrere med ForeningLet.dk først logge på med et brugernavn og kodeord. Dette foregår via HTTP Basic Authentication, som eksempelvis kan gøres på følgende måde via kommandolinjeværktøjet curl:

curl https://foreninglet.dk/api/members?version=1 -u {brugernavn}:{kodeord}

Parameteren version er obligatorisk og fortæller hvilken version af API’et, som tilgås. Nuværende version er 1.

Parameteren efter -u er brugernavn og kodeord adskilt af et kolon. Brugernavn og kodeord kan ses af foreningens administrator under “Opsætning -> Integrationer -> API”.

Kodeordet (i kombination med brugernavnet) giver adgang til foreningens data, hvorfor kodeordet ikke må udleveres til tredjepart, da tredjepart dermed kan få adgang til foreningens data.

URL’en https://foreninglet.dk/api/members?version=1 kan også indtastes i en browser, hvorefter browseren vil spørge om brugernavn og kodeord. På denne vis er det let at afprøve API’et.

Versionering

Klienten skal altid angive URL-parameteren version på en forespørgsel. Dermed sikres det, at API’et løbende kan udvides uden at bryde kontrakten med eksisterende klienter, idet en given version aldrig vil ændre på navngivning eller fjerne et felt i de svar som API’et returnerer til klienten.

Når der sker ændringer til API’et, så sker det altid via tilføjelsen af en ny version af API’et, således at klienter, som ikke kører på nyeste version, stadig virker.

Hvis en ældre version af API’et udgår, så bliver de foreninger som anvender den pågældende version af API’et notificeret i rimelig tid. Typisk vil en forening blot kunne ændre til nyeste version af API’et uden at skulle foretage kodeændringer i klienten.

Begrænsninger i antal forespørgler

Der er en øvre grænse for hvor mange forespørgsler man må lave mod API’et per time. Grænsen er 10.000 forespørgsler i timen.

Hvis grænsen overskrides vil API’et svare tilbage med en HTTP 429 (“Too Many Requests”).

Protokol og dataformat

Der integreres via https-protokollen. API’et bygger på principperne bag REST.

Dataformatet er json. Hvis en klient ønsker et svar i et andet format, fx html (eller xml), så tilføj følgende URL-parametre til forespørgslen: /format/html. Eksempelvis: https://foreninglet.dk/api/members/format/html?version=1

Når der oprettes nye data (POST) eller opdateres eksisterende data (PUT), så skal “Content-Type: application/json” altid angives i forespørgslen.

Tidsstempler følger ISO8601 og vil altid blive vist i UTC.

Når der oprettes eller opdateres en ressource, vil svaret være at finde i body formateret som json, og der sættes en Location http header som peger på ressourcen.

Begrænsninger og ansvar

Jeres abonnement på ForeningLet gør det muligt at få adgang til at bruge et API, herunder at udvikle og implementerer integrationer til brug i forbindelse med jeres abonnement på ForeningLet til jeres interne forretningsformål.

For at kunne bruge og få adgang til API’et, skal I bruge API brugernavn og kodeord, som er tilgængeligt hvis man er oprettet i ForeningLet. I må ikke dele dette brugernavn og kodeord, og skal opbevare det sikkert. Brugernavn og kodeord er den eneste måde, hvorigennem I har tilladelse til at få adgang til API’et.

I må ikke bruge API’et til at kopiere produkter eller tjenester, der tilbydes af ForeningLet, herunder funktioner eller klienter på platforme (såsom iOS eller Android) hvor ForeningLet tilbyder sin egen klient eller funktion.

I må ikke videresælge API’et. I må ikke bruge API’et på nogen måde, der potentielt kunne underminere sikkerheden i API’et.

I er eneansvarlige (og ForeningLet har intet ansvar af nogen art), for indholdet, udvikling, drift eller vedligeholdelse af de integrationer I måtte udvikle via API’et. I er eneansvarlige for at jeres integrationer ikke overtræder eller krænker immaterielle rettigheder tilhørende en tredjepart.

I skal respektere og overholde de tekniske og politiske implementerede begrænsninger af API’et.

I det omfang I udvikler eller implementere integrationer, der sender eller på anden måde bruger API’et til at overføre jeres data uden for ForeningLet, vil I være ansvarlige for eventuelle nødvendige anmeldelser til eller samtykker fra slutbrugere om at deres data vil blive sendt uden for ForeningLet. ForeningLet er ikke ansvarlig for sikkerhed eller integritet i jeres data, i det omfang de sendes uden for ForeningLet via jeres integrationer til API’et.

API-kald

Her følger en liste over de forskellige kald til API’et.

Medlemsliste

GET /api/members

Følgende kald returnerer alle medlemmerne

curl https://foreninglet.dk/api/members?version=1 -u {brugernavn}:{kodeord}

Opret medlem

POST /api/member

Når man opretter et medlem, så skal man som minimum angive et fornavn.

Eksempel på forespørgsel

{
  "member": {
    "first_name": "Hans Christian",
    "last_name": "Andersen"
  }
}

Via curl

curl https://foreninglet.dk/api/member?version=1 \
  -d '{"member": {"first_name": "Hans Christian","last_name": "Andersen"}}' \
  -H "Content-Type: application/json" -u {brugernavn}:{kodeord} -X POST

Eksempel på svar

Status: 201 Created
Location: https://foreninglet.dk/api/member/id/1?version=1
{
  "member": {
    "id": 12345,
    "display_id": 1,
    "first_name": "Hans Christian",
    "last_name": "Andersen",
    "address": "",
    "address2": "",
    "zip": "",
    "city": "",
    "email": "",
    "email2": "",
    "email3": "",
    "phone": "",
    "mobile": "",
    "gender": 2,
    "birthday": "0000-00-00",
    "country_code": "",
    "ean_number": "",
    "enrollment": "0000-00-00",
    "resignation_date": "0000-00-00",
    "password": "63C4B",
    "field1": "",
    "field2": "",
    "field3": "",
    "field4": "",
    "field5": "",
    "field6": "",
    "field7": "",
    "field8": "",
    "field9": "",
    "field10": "",
    "created": "2015-06-18T12:02:14+0000",
    "updated": "2015-06-18T12:02:14+0000",
    "activity_ids": [],
    "cpr_number": "",
    "reg_number": "",
    "account_number": ""
  }
}

Systemet tildeler automatisk et kodeord til nye medlemmer. Man kan også angive et kodeord i oprettelsen.

Parametre

Når der oprettes et nyt medlem via POST, så kan der angives følgende parametre, hvoraf first_name er den eneste obligatoriske parameter.

Navn Beskrivelse
display_id Medlemsnr.
first_name Fornavn
last_name Efternavn
address Adresse
address2 Adresse 2
zip Postnr.
city By
email Email-adresse
email2 Email-adresse 2
email3 Email-adresse 3
phone Telefonnr.
mobile Mobilnr.
gender Køn (0=kvinde, 1=mand, 2=intet køn angivet)
birthday Fødselsdato
country_code Landekode (ISO 3166 - 2 bogstaver)
ean_number EAN-nr.
enrollment Indmeldelsedato
resignation_date Udmeldelsesdato
password Kodeord
field1 Felt 1
field2 Felt 2
field3 Felt 3
field4 Felt 4
field5 Felt 5
field6 Felt 6
field7 Felt 7
field8 Felt 8
field9 Felt 9
field10 Felt 10
activity_ids ID’er på aktiviteter
cpr_number CPR-nummer
reg_number Registreringsnummer i bank
account_number Kontonummer i bank

Hvis der ikke angives et medlemsnr., så tildeler systemet selv det næste ledige medlemsnr.

Bemærk

Betalingsservice: Hvis felterne CPR-nummer, registreringsnummer og kontonummer er udfyldt, og foreningen er sat op til at bruge Betalingsservice, så vil systemet automatisk forsøge at oprette en PBS-aftale på det nye medlem.

Opdater medlem

PUT /api/member/id/{id}

Når man opdaterer et medlem, skal man angive ID på det medlem som ønskes opdateret. ID’er på medlemmerne returneres fra API-kaldet til medlemslisten. Bemærk at felterne id og display_id er 2 forskellige felter, hvor id er det interne databasenr. som er unikt for medlemmet og bruges i API-kald, mens display_id svarer til medlemmets medlemsnr.

Man kan nøjes med at angive de felter man gerne vil ændre.

Vær opmærksom på at hvis man angiver en tom liste af aktivitets-ID’er, så bliver medlemmets eventuelle tildelte aktiviteter slettet. Hvis man ikke ønsker at påvirke medlemmets aktiviteter, så skal man helt undlade at anvende feltet activity_ids. I det øjeblik feltet activity_ids er sat, så vil medlemmet få opdateret sin samlede liste af aktiviteter til præcis kun at indeholde de angivne aktiviteter. Således kan aktiviteter også blive slettet.

Eksempel på forespørgsel

{
  "member": {
    "first_name": "Hans Christian",
    "last_name": "Jensen"
  }
}

Via curl

curl https://foreninglet.dk/api/member/id/{id}?version=1 \
  -d '{"member": {"first_name": "Hans Christian","last_name": "Jensen"}}' \
  -H "Content-Type: application/json" -u {brugernavn}:{kodeord} -X PUT

Eksempel på svar

Status: 200 OK
{
  "member": {
    "id": 12345,
    "display_id": 122153,
    "first_name": "Hans Christian",
    "last_name": "Jensen",
    "address": "",
    "address2": "",
    "zip": "",
    "city": "",
    "email": "",
    "email2": "",
    "email3": "",
    "phone": "",
    "mobile": "",
    "gender": 2,
    "birthday": "0000-00-00",
    "country_code": "",
    "ean_number": "",
    "enrollment": "0000-00-00",
    "resignation_date": "0000-00-00",
    "password": "63C4B",
    "field1": "",
    "field2": "",
    "field3": "",
    "field4": "",
    "field5": "",
    "field6": "",
    "field7": "",
    "field8": "",
    "field9": "",
    "field10": "",
    "created": "2015-06-18T12:02:14+0000",
    "updated": "2015-06-18T12:02:16+0000",
    "activity_ids": []
  }
}

Login

POST /api/memberlogin

Når man vil lave et login på et medlem, så skal man angive et brugernavn og et kodeord. Brugernavnet kan være medlemsnr. eller email-adresse, og dette styres i parameteren field, der som udgangspunkt er sat til email. Den anden mulighed er member_number.

Hvis medlemmet har status som indmeldt og brugernavn og kodeord matcher, så returneres medlemmets detaljer.

Følgende er et eksempel på login med email-adresse test@foreninglet.dk samt kodeord 12345.

Eksempel på forespørgsel

{
  "credentials": {
    "username": "test@foreninglet.dk",
    "password": "12345",
    "field": "email"
  }
}

Via curl

curl https://foreninglet.dk/api/memberlogin?version=1 \
  -d '{"credentials": {"username": "test@foreninglet.dk","password": "12345", "field": "email"}}' \
  -H "Content-Type: application/json" -u {brugernavn}:{kodeord} -X POST

Eksempel på svar

Status: 200 OK
{
    "id": 12345,
    "display_id": 1000,
    "first_name": "Hans",
    "last_name": "Jensen",
    "address": "",
    "address2": "",
    "zip": "",
    "city": "",
    "email": "test@foreninglet.dk",
    "password": "12345"
}

Ovenstående svar et blot et udsnit af de medlemsinformationer som returneres, hvis medlemmet findes.

Hvis medlemmet ikke findes, så returneres følgende svar:

Status: 404 OK
{
        "error":"Member with username [test@foreninglet.dk] could not be found"
}

Aktivitetsliste

GET /api/activities

Følgende kald returnerer alle aktiviteter

curl https://foreninglet.dk/api/activities?version=1 -u {brugernavn}:{kodeord}

Eksempel på svar

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "ActivityId": "11111",
        "Categories": ["Ungdomsafdelingen"],
        "ExternalDescriptions": [],
        "Name": "Ungdomskontingent",
        "OnlineEnrollmentEnabled": "0"
    },
    {
        "ActivityId": "22222",
        "Categories": ["Seniorafdelingen"],
        "ExternalDescriptions": [],
        "Name": "Seniorkontingent",
        "OnlineEnrollmentEnabled": "0"
    },
    {
        "ActivityId": "33333",
        "ExternalDescriptions": [
            {
                "Headline": "Tilmelding \u00e5bner",
                "Text": "1. august 2018, kl. 12:00"
            },
            {
                "Headline": "Nye medlemmer",
                "Text": "Hvis du \u00f8nsker at blive medlem af foreningen, s\u00e5 klik p\u00e5 'Tilmeld'."
            }
        ],
        "Name": "Nye medlemmer",
        "OnlineEnrollmentEnabled": "1"
    }
]

Ovenstående eksempel viser et svar med 3 aktiviteter. Én af aktiviteterne er åben for online tilmelding, hvilket kan aflæses i feltet OnlineEnrollmentEnabled, hvor værdien er sat til 1. Hvis en aktivitet er åben for online tilmelding, så vil der også være udfyldt en række beskrivelser af aktiviteten i feltet ExternalDescriptions, som er en liste med overskrifter og tekster.

Hvis man vil bruge aktivitetslisten til at lave en tilmeldingsliste på sin egen hjemmeside, så kan man bruge ActivityID til at linke dybt fra denne liste på hjemmesiden og ind i medlemsportalen, hvilket fx kan gøres sådan her:

https://<forenings-ID>.foreninglet.dk/memberportal/teamenrollment/subscribe/<ActivityID>

Man skal naturligvis erstatte forenings-ID og ActivityID med de rigtige værdier. Foreningens ID kan ses inde i systemet, når man er logget ind ved at klikke på menupunktet “Medlemsportal”.

Opret opkrævning

POST /api/invoice

Når man opretter en opkrævning, så skal man som minimum angive medlems-ID (bemærk at medlems-ID ikke er det samme som medlemsnr.), en beskrivelse af hvad der opkræves samt beløbet der skal opkræves.

Eksempel på forespørgsel

{
  "invoice": {
    "member_id": 123456,
    "description": "Kontingent",
    "amount": 100.00
  }
}

Via curl

curl https://foreninglet.dk/api/invoice?version=1 \
  -d '{"invoice": {"member_id": 123456, "description": "Kontingent", "amount": 100.00}}' \
  -H "Content-Type: application/json" -u {brugernavn}:{kodeord} -X POST

Eksempel på svar

Status: 201 Created
Location: https://foreninglet.dk/api/invoice/id/1000?version=1
{
  "invoice": {
    "credit_card_payment_url": "https://foreninglet.dk/main/apiredirectcreditcardwindow/{x}"
    "id": 1000,
    "text": "Kontingent",
    "total_amount": 100
  }
}

Systemet tildeler automatisk et opkrævningsnr. til en ny opkrævning. Det findes i feltet “id”.

I svaret er der en vigtig parameter ved navn credit_card_payment_url, som indeholder en adresse. Hvis der redirectes til denne adresse, så åbnes et betalingsvindue, hvor medlemmet kan betale opkrævningen med kreditkort. Det er naturligvis en forudsætning, at dankortmodulet er tilkøbt og sat op.

Opret booking

POST /api/booking

Når man opretter en booking, så skal man som minimum angive ID på den ressourcekalender der bookes i og ID på den ressource som bookingen vedrører samt start- og slutdato, samt en tekst eller en række medlems-IDer.

Eksempel på forespørgsel

{
  "booking": {
    "resource_calendar": 5678,
    "resource_id": 1234,
    "text": "Generalforsamling",
    "start_date": "2017-11-14T18:00:00+0000",
    "end_date": "2017-11-14T20:00:00+0000",
    "create_timed_code": "true",
  }
}

Via curl

curl https://foreninglet.dk/api/booking?version=1 \
  -d '{"booking": {"resource_calendar_id": 5678, "resource_id": 1234, "text": "Generalforsamling", "start_date": "2017-11-14T18:00:00+0000", "end_date": "2017-11-14T20:00:00+0000", "create_timed_code": "true"}}' \
  -H "Content-Type: application/json" -u {brugernavn}:{kodeord} -X POST

Eksempel på svar

Status: 201 Created
Location: https://foreninglet.dk/api/booking/id/1000?version=1
{
  "booking": {
    "id": 1000,
    "resource_calendar_id": 5678,
    "resource_id": 1234,
    "text": "Generalforsamling",
    "start_date": "2017-11-14T18:00:00+0000",
    "end_date": "2017-11-14T20:00:00+0000",
    "created": "2017-11-07T16:42:14+0000",
    "timed_code": 476294
  }
}

Systemet tildeler automatisk et booking-ID til en ny booking. Det findes i feltet “id”.

Hvis man har sat “create_timed_code” til “true”, så vil systemet danne en 6-cifret kode som kan anvendes i dørsystemet (hvis dette er installeret), og give adgang til bookingen i det tidsrum der omkranser bookingens start- og sluttidspunkt.

Ressourcekalenderen definerer en række regler på de ressourcer som indgår i kalenderen. En ressourcekalender indeholder typisk én til flere ressourcer. Hvis det er booking af badmintonbaner, så vil en ressourcekalender typisk svare til en hal, og ressourcerne vil være de baner som er i hallen.

Slet booking

DELETE /api/booking/id/{id}

Når man sletter en booking, så skal man angive ID på den booking man ønsker at slette.

Via curl

curl https://foreninglet.dk/api/booking/id/1234?version=1 \
  -H "Content-Type: application/json" -u {brugernavn}:{kodeord} -X DELETE

Eksempel på svar

Status: 200 Deleted
{"id":"1234","message":"DELETED!"}

Systemet sletter også en eventuel kode til dørsystemet, hvis sådan en kode er tilknyttet bookingen.

Bookingliste

GET /api/bookings/start_date/{startdato}/end_date/{slutdato}

Når man henter en bookingliste, så skal man som minimum angive start- og slutdato, som vist ovenfor. Systemet returnerer alle bookinger som er indenfor det angivne datointerval.

Formatet på datoen skal være ÅÅÅÅ-MM-DD - fx 2018-12-24, hvilket er juleaften.

Via curl

curl https://foreninglet.dk/api/bookings/start_date/{startdato}/end_date/{slutdato}?version=1 -u {brugernavn}:{kodeord}

Eksempel på svar

HTTP/1.1 200 OK
Content-Type: application/json

[
    {
        "activity_id": "0",
        "created": "2017-02-27T10:56:12+0000",
        "created_by": "admin",
        "end_time": "2017-12-01T13:00:00+0000",
        "id": "99128",
        "resource_id": "1234",
        "start_time": "2017-12-01T11:00:00+0000",
        "text": "Booking af bane 1",
        "url": ""
    },
    {
        "activity_id": "0",
        "created": "2017-07-31T21:13:52+0000",
        "created_by": "kontakt@kbknet.dk",
        "end_time": "2017-12-01T19:00:00+0000",
        "id": "124282",
        "resource_id": "1235",
        "start_time": "2017-12-01T15:00:00+0000",
        "text": "Booking af bane 2",
        "url": ""
    }
]

Bemærk at start_time og end_time i ovenstående svar er angivet i UTC.