The making of a great API

A presentation at Dutch PHP Conference 2019 in June 2019 in Amsterdam, Netherlands by Rob Allen

Slide 1

Slide 1

THE MAKING OF A GOOD API ROB ALLEN N I N E T E E N F E E T LT D S L I D E S : H T T P S : / / A K R A B AT. C O M / 5 7 5 7 @akrabat

Slide 2

Slide 2

FIT FOR PURPOSE

Slide 3

Slide 3

F E AT U R E S O F A G O O D A P I • Malleability • Correctness • Error handling • Documentation • Security @akrabat

Slide 4

Slide 4

A GOOD API IS MALLEABLE

Slide 5

Slide 5

D E C O U P L E Y O U R R E P R E S E N TAT I O N @akrabat

Slide 6

Slide 6

HYPERMEDIA • An explorable API • Rename end points at will • Re-home end points on different servers @akrabat

Slide 7

Slide 7

HYPERMEDIA { } “_links”: { “self”: { “href”: “https://api.example.com/orders/523” }, “customer”: { “href”: “https://api.example.com/customers/32” }, “invoice”: { “href”: “https://api.example.com/invoices/873” }, “shippingNote”: { “href”: “https://cdn.example.com/ad8wd4.pdf”, “type”: “application/pdf” } }, “currency”: “GBP”, “status”: “shipped”, “total”: 123.45 @akrabat

Slide 8

Slide 8

A GOOD API IS CORRECT

Slide 9

Slide 9

EMBRACE HTTP VERBS METHOD USED FOR IDEMPOTENT? GET Retrieve data Yes PUT Change data Yes DELETE Delete data Yes PATCH Update data No POST Change data No @akrabat

Slide 10

Slide 10

S TAT U S C O D E S M AT T E R 1xx Informational 2xx Success 3xx Redirection 4xx Client error 5xx Server error @akrabat

Slide 11

Slide 11

MEDIA TYPES • Read Content-Type header to decode incoming data • Honour the Accept header when sending data @akrabat

Slide 12

Slide 12

HANDLING CHANGES • Avoid major new versions • Make changes backwards-compatible • Think about forwards-compatibility @akrabat

Slide 13

Slide 13

A NEW VERSION IS A NEW API • Separate code • Domain or URL path is fine • api.example.com/v2/user • api2.example.com/user • Use Server header for minor and patch info @akrabat

Slide 14

Slide 14

A GOOD API HAS G R E AT E R R O R S

Slide 15

Slide 15

G R E AT E R R O R H A N D L I N G • Error representations are first class citizens • Code for computers; messages for humans • Pretty print for the humans! @akrabat

Slide 16

Slide 16

HTTP PROBLEM (RFC 7807) HTTP/1.1 503 Service Unavailable Content-Type: application/problem+json Content-Language: en { } “status”: 503, “type”: “https://example.com/service-unavailable”, “title”: “Could not authorise user due to an internal problem.”, “detail”: “The authentication service is down for maintenance.”, “instance”: “https://example.com/maintenance-schedule/2017-06”, “error_code”: “AUTHSERVICE_UNAVAILABLE” @akrabat

Slide 17

Slide 17

A GOOD API IS DOCUMENTED

Slide 18

Slide 18

PROFILE LINKS (RFC 6906) Header: Link: https://www.example.com/docs;rel=”profile” Body: { } “_links”: { “profile”: { “href”: “https://www.example.com/docs/” } } @akrabat

Slide 19

Slide 19

H U M A N D O C U M E N TAT I O N • Tutorials • Reference @akrabat

Slide 20

Slide 20

O P E N A P I S P E C I F I C AT I O N • Spec-First API Design • Tooling: https://openapi.tools @akrabat

Slide 21

Slide 21

A GOOD API IS SECURE

Slide 22

Slide 22

OAUTH 2 • Application identification • User identification • User’s trust relationship is with the API @akrabat

Slide 23

Slide 23

R AT E L I M I T HTTP/1.1 429 Too Many Requests Content-Type: application/problem+json X-RateLimit-Limit: 5000 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1471549573 { } “status”: 429, “type”: “https://dev.example.com/rate_limits”, “title”: “API rate limited exceeded.”, “error_code”: “RATE_LIMIT_EXCEEDED” @akrabat

Slide 24

Slide 24

TO SUM UP

Slide 25

Slide 25

THANK YOU HTTPS://JOIND.IN/EVENT/DUTCH-PHP-CONFERENCE-2019 ROB ALLEN @akrabat