Generella krav
Allmänt
All API-kommunikation sker i json.
Klienten skickar Accept: application/json i samtliga requests och
förväntar sig Content-Type: application/json i framgångsrika svar.
Versionshantering
Alla API:er skall versioneras med hjälp av URI:n. Den första versionen
skall vara v1. Inga bakåtbrytande ändringar får göras i en version,
istället skall en ny version skapas.
När en ny version skapas skall den gamla versionen finnas kvar under någon tidsperiod för att tillåta migrering. Alla endpoints ska finnas i alla versioner även om dom inte har ändrats.
Exempel på ändringar som tillåts inom en version
- Lägga till nya fält i ett svar
- Lägga till nya API:er
- Lägga till nya feltyper
Autentisering
API:t skall använda sig av
OAuth 2.0
med JSON Web Tokens (JWT)
i JSON Web Signature (JWS)
format för autentisering och avgöra behörigheter på principalen (sub)
som identifieras av token och eventuella entitlements.
För mer information se https://oauth2.dsv.su.se/
Identifiering av personer
Personer ska i både förfrågningar och svar identifieras via fullt
kvalificerad principal, t.ex foobar@su.se. Om flera identiteter
existerar för samma person så ska i möjligaste mån en identitet i samma
domän som den autentiserade användarens returneras. Den autentiserade
användarens domän är den domän som står i förfrågningens JWT-token
i fältet sub.
Användardefinerade strängar
När en användare skickar data i form av en sträng till ett API, t.ex
namnet på en bokning, så ska helt arbiträr UTF-8 accepteras. Mottagaren
ansvarar för att hantera indata på ett säkert sätt som inte äventyrar
applikationens integritet via t.ex injection-attacker. När samma sträng
returneras via en request faller ansvaret för sanering på mottagaren.
API:er får sätta tillåtna max-längder på strängar skickade från klienten per applicerbart fält. Sådana begränsningar ska dokumenteras. Detaljerna i hur längden på en sträng räknas (codepoints, bytes, etc) är oviktiga - det måste inte gå att skicka 50 emojis om teckengränsen är 50 tecken. Gränsen ska vara satt så att förväntade rimliga indata stöds.
Datum och tid
Alla datum, klockslag och tidsintervall ska uppfylla ISO8601.
-
Datum:
YYYY-MM-DD -
Tid:
hh:mm:ss -
Datum+tid:
YYYY-MM-DDThh:mm:ss
Tanvänds som separator mellan datum- och tidsdelen. -
Tidsintervall:
PnYnMnDTnHnMnS
Det generella formatet ärPför "Period", följt av antal år/månader/dagar, följt avTför "Time", följt av antal timmar/minuter/sekunder. Enheter som inte används förväntas utelämnas.Exempel:
P1DT3H: 1 dag, 3 timmarPT2H: 2 timmarP4Y: 4 år
Internationalisering
Om ett fält kan populeras med data på flera språk skall värdet baseras på
HTTP headern
Accept-Language
och språket ska anges i svaret med hjälp av
Content-Language.
Om inget av språken i Accept-Language finns skall det först falla
tillbaka på engelska och om även det saknas falla tillbaka på svenska.
Denna internationalisering måste även appliceras på felmeddelanden, t.ex
title, detail, och eventuella extra attribut.
Exempel med språk som stöds
> GET /lokal
> Accept-Language: sv
< 200 OK
< Content-Language: sv
{
"name": "Mötesrum"
}
Exempel med språk som inte stöds
> GET /lokal
> Accept-Language: de
< 200 OK
< Content-Language: en
{
"name": "Meeting room"
}
Prestandakrav
99% av alla giltiga förfrågningar måste svaras på inom 100ms. Detta måste gälla hela tiden genom att mäta i ett kort rullande fönster, inte bara genomsnittligt över en längre period.
Felhantering
Fel anges i formatet specifierat i RFC 7807 (Problem details).
Specifikation
Felmeddelanden returneras som JSON-data med
Content-type: application/problem+json.
Följande fält är obligatoriska:
-
type:string
Felmeddelandets typ. Typen ska vara en av en dokumenterad uppsättning strängar på formatetapplikation:feltyp. Formatet påfeltyp-delen är upp till applikationen, men måste vara dokumenterat. -
title:string
En beskrivning av feltypen avsedd att presenteras för användaren. Värdet på det här fältet förväntas vara samma för alla fel av sammatype. Värdet ska vara internationaliserat och meningsfullt för en användare. -
detail:string
En beskrivning av det här felets specifika omständighter avsedd att presenteras för användaren. Meddelandets fokus ska vara att hjälpa användaren förstå och åtgärda vad som gått fel (om möjligt - en användare kan inte på egen hand ge sig själv nya rättigheter t.ex). -
instance:string
Den lokala URL i applikationen som anropades av klienten då felet uppstod.
Extra fält
Alla feltyper en applikation dokumenterar får inkludera extra fält avsedda att underlätta för den mottagande applikationen att presentera felet för användaren. Sådana extra fält ska dokumenteras tillsammans med övrig information om feltypen.
T.ex skulle ett formulärfel kunna inkludera en lista på fält som inte klarade validering. Se nedan för ett exempel.
Exempel på fel
De här exemplen är inte avsedda att ses som specifikation på förväntade feltyper, utan bara illustrera hur fel förväntas formateras.
Ej behörig
< 403 Forbidden
< Content-Type: application/problem+json
< Content-Language: en
{
"type": "daisy:forbidden",
"title": "You can not perform this action",
"detail": "You may not book a group room because you are not a student at SU",
"instance": "/v1/bookings/group-rooms"
}
Misslyckad validering av indata
< 400 Bad request
< Content-Type: application/problem+json
< Content-Language: en
{
"type": "daisy:bad-request",
"title": "Bad request",
"detail": "Request contents did not pass validation",
"instance": "/v1/bookings/group-rooms",
"violations": {
"start_time": "Must be in format YYYY-MM-DDThh:mm:ss",
"name": "Too long, max 100 characters"
}
}
För lång bokning
< 400 Bad request
< Content-Type: application/problem+json
< Content-Language: sv
{
"type": "daisy:duration-too-long",
"title": "Bokningen överskrider maxlängden",
"detail": "Du försökte boka 5 timmar, men maxlängden är 4 timmar",
"instance": "/v1/bookings/group-rooms"
}
För få deltagare
< 400 Bad request
< Content-Type: application/problem+json
< Content-Language: en
{
"type": "daisy:too-few-participants",
"title": "Booking needs more participants",
"detail": "You may only book with at least two participants, not by yourself",
"instance": "/v1/bookings/group-rooms"
}