APIs for the
Mobile World
Michele Titolo
Lead Software Engineer @ Capital One
Why APIs for the
world?mobile
People 💖 Apps
Apps Have To Be
Great 👍
Apps Are
Complicated
📶
🔗
🕐‼
👑
Can APIs make an
app not great? Yes.
How?
Slow 💤
State 🙅
Crashes 💥
Oops something’s amiss
Slows Down
Development
great📱
5ways to make
experiences
Keep Things Consistent.1
Established
Conventions
Don’t Return 200
With “Error”
Follow Your Own
Conventions
Endpoint “id” field
/products id
/products/:id productID
/cart product_id
Document Everything.2
does not
self documenting
code
exist
Ask So And So Is Not
Documentation
Update
Documentation
Communicate
Make
Documentation Part
Of The Process
Auto-Generate
Honor thy contracts.3
Documentation Is A
Contract
Versioning
Unexpected
Breaking Changes
http://
500s that return
HTML
Insulate the client.4
Something
WILL PROBABLY
GO
WRONG
Long Release Cycles
Releasing An App
Doesn't Mean People
Will Use It
Gateway Or Reverse
Proxy
The Bigger Your
Ecosystem, The More
This Is Needed
Route To Different
Servers
Mutate Requests And
Responses
Zuul
Make an API just for
mobile
.5
Backend For
Frontend
Tailor APIs to Mobile
Experiences
Not A New Concept
Why?
Rest
Representational State Transfer
= Data
Imagine…
The most amazing movie
app in the world
Lets Add A
New Feature
Show nearby movie times
# Obtain a list of movies

GET /movies

# Obtain a list of nearby theatres

GET /theatres?lat=…&long=…

# Obtain the showing times for a theatre

GET /theatres/1234/times
server.makeMoviesRequest { (movieList, error) in
if error {
// handle error case
} else {
// handle success case
}
}
server.makeMoviesRequest { (movieList, error) in
if error {
// handle error case
} else {
// handle success case
}
}
server.makeTheatresRequest(lat,long) { (theatreList, error) in
if error {
// handle error case
} else {
// handle success case
}
}
var moviesRequestComplete: Bool = false
var theatresRequestComplete: Bool = false
server.makeMoviesRequest { (movieList, error) in
if error {
// handle error case
} else {
moviesRequestComplete = true
// do something with the data
}
}
server.makeTheatresRequest(lat,long) { (theatreList, error) in
if error {
// handle error case
} else {
theatresRequestComplete = true
// do something with the data
}
}
func makeInitialServerCalls () {
var moviesRequestComplete: Bool = false
var theatresRequestComplete: Bool = false
server.makeMoviesRequest { (movieList, error) in
if error {
// handle error case
} else {
moviesRequestComplete = true
// do something with the data
}
}
server.makeTheatresRequest(lat,long) { (theatreList, error) in
if error {
// handle error case
} else {
theatresRequestComplete = true
// do something with the data
}
}
}
func makeTheatreTimesRequest(for: theatres) {
for theatre in theatres {
server.makeTheatreTimesRequest(theatre.id) {
if error {
// handle error case
} else {
// process movie times
}
}
}
}
func makeInitialServerCalls () {
var moviesRequestComplete: Bool = false
var theatresRequestComplete: Bool = false
server.makeMoviesRequest { (movieList, error) in
if error {
// handle error case
} else {
moviesRequestComplete = true
self.movies = movieList
}
}
server.makeTheatresRequest(lat,long) { (theatreList, error) in
if error {
// handle error case
} else {
theatresRequestComplete = true
makeTheatreTimesRequest(for: theatreList)
}
}
}
func makeTheatreTimesRequest(for: theatres) {
let closestTheatres = theatres..3 // get 3 closest theatres
for theatre in closestTheatres {
if !requestTimesForTheatreAndReturnIfAnotherRequestShouldBeMade(theatre) {
break
}
}
}
func requestTimesForTheatreAndReturnIfAnotherRequestShouldBeMade(theatre) {
server.makeTheatreTimesRequest(theatre.id) {
if error {
// handle error case
} else {
// process movie times
}
}
}
func makeInitialServerCalls () {
var moviesRequestCompletedSucessfully: Bool = false
var theatresRequestComplete: Bool = false
server.makeMoviesRequest { (movieList, error) in
if error {
// handle error case
} else {
moviesRequestCompletedSucessfully = true
self.movies = movieList
}
}
server.makeTheatresRequest(lat,long) { (theatreList, error) in
if error {
// handle error case
layoutMovies()
} else {
theatresRequestComplete = true
if moviesRequestCompletedSuccessfully {
makeTheatreTimesRequest(for: theatreList)
}
}
}
}
func makeTheatreTimesRequest(for: theatres) {
let closestTheatres = theatres..3 // get 3 closest theatres
var theatreTimesAPIsFinished: Bool = false
for theatre in closestTheatres {
if !requestTimesForTheatreAndReturnIfAnotherRequestShouldBeMade(theatre) {
theatreTimesAPIsFinished = true
break
}
}
layoutMovies()
}
func requestTimesForTheatreAndReturnIfAnotherRequestShouldBeMade(theatre) {
server.makeTheatreTimesRequest(theatre.id) {
if error {
// handle error case
} else {
// process movie times
}
}
}
‼
❓
🚫
🙀
💩
Multiple Client
Implementations
More Bugs
Error Scenarios
Times Many
Release Dependent
Changes
Release Dependent
Experiments
Resource Based Apis
Make Creating
Experiences Difficult
Solution: Apis For
Mobile Experiences
Logic Has To Live
Somewhere
Easier To Release
And Iterate
Makes Mobile
Development Easier
Great Experiences
1. Keep It Consistent
2. Document Everything
3. Honor Thy Contracts
4. Insulate The App
5. Make Something Special
In Summary
Thank You!
@micheletitolo
• https://unsplash.com/search/phone?
photo=0VGG7cqTwCo
• https://unsplash.com/search/phone?
photo=UGX2qdjdKkw
Photo Credits

APIs for the Mobile World