 Thank you for coming. I hope everybody enjoyed DHH's keynote and are all ready to build monolithic web apps. We're going to talk today about API design. And specifically API design that is focused on the people who actually have to write code against that API. We are not going to be doing any coding at all today. Implementation is an implementation detail. So don't worry. We're just going to design it really well and then implementing it as somebody else's problem. My name is Pete Holliday. I'm a lead engineer at MailChimp. MailChimp is an email service company and we will tell you much more about it later. I'm Kate Harlin. I'm an engineering intern at MailChimp and graduate from Georgia Tech next week. And after you graduate from Georgia Tech, what are you going to do then? I'm going to come back to MailChimp and work there full time. Virgin 2.0 of our API did a lot of things well. About 250,000 users hit it every single day. Billions of requests come and go. And it's fairly popular. We did a survey not that long ago and we found 75% of people thought that it was good or excellent, which those are really good numbers. But as we were working with it ourselves, we discovered that there were some pretty big issues with the design of it and with the things that people are trying to do with it. And so this talk is sort of a came out of that process of us designing our newest version of our API, which is currently in beta. It was supposed to be released a month or so ago, but software happens and so it's late. We're also, this is going to be a fairly interactive session. So during several portions, you're going to need to probably chat with your neighbors. And so if you would, just take a moment, introduce yourself to your neighbors. Any of your neighbors you don't know, you're going to become good friends by the end of this. So just make yourselves friendly. All right, I think you've got the next one, is that right? I want to know the gender ratio of the whole conference, I'm just curious. Yeah, I think it's pretty good, but it's still kind of white nail-y. Yeah, I mean, just looking around, there's like average ish one, from what my perception is there's average ish one woman a row, like four, like half of one in eight maybe. Okay, okay, okay, not that friendly. Okay, all right, let's bring it back. Bring it back, bring it back. I've lost the room already. All right, bring it back in, awesome. All right, so y'all probably at least kind of know what an API is already, but it stands for application program interface. APIs are pretty much everywhere. If you've done any programming at all, you've used an API, because that's just interfacing with that program. And APIs are just the way two pieces of software communicate across a boundary, and there are all kinds of different boundaries everywhere you look. Ruby blocks are an example of a boundary. Language features typically are APIs of that language. Class methods, more generally object-oriented programming, all of the classes that you generate expose APIs. And then of course the thing that we're here today to talk about, web services. They could even be microservices if you wanted them to be. Ah, yeah, yeah, I know. And the principles that you use to design a web service API, they're going to be very similar to the principles that you would use to design any other kind of API. But we'll be using web services as sort of the thing we talk about today. I don't know, is it possible to dim the lights? Sure. I guess it's hard to read in the light. Is that what I'm hearing? The screen is hard to read? He's working on it. It wouldn't be my first. All right, so while we're working on that, I'll just keep on trucking, I guess. Developer-focused APIs, they sort of mirror the movement we've seen over the past, who knows how many years to bring user experience in web apps. For that to be a focus, I guess. And I've noticed that that hasn't really been mirrored in API design. APIs are still very much just sort of the Wild West in terms of how they look. And so when we talk about developer-focused API design, we're talking about optimizing for the end user and not for your back-end systems. Many APIs are designed to make them easy to implement and to maintain, but they're not necessarily easy for the end user to use. And when you focus on the end user, the person who's going to end up eventually using your API, that leads to great experiences in developing those. So what do developers want when they are using your API? Well, if you think about any time you've used an external API, developers want basically one thing. They want to get in, they want to get done, and they want to get out. And they never want to touch your API again. Ideally, that is the thing that they want the most, is to just get their sprint done and be done. So never return is sort of an important part of that. Because once they write something using your API, you can't just change how it works because then you'll break everybody's everything and everyone will be sad. So you have to version your APIs, which is really important, but also the versions that you put out have to be robust and functional. So who here has had a bad API experience? Raise your hand, show of hands. All right, so a couple of you. Good, so for a moment, for let's say 90 seconds, talk with your neighbors about what made those experiences bad. What was it about the API experiences you had that made them challenging? And when you're done, I'm going to ask you to actually contribute and raise your hands and tell us what it was that you thought. I never go anywhere without a water bottle. And I sort of have not been living in my apartment as much as usual. And so I keep losing water bottles. I don't know where they go. I really appreciate it. Thank you so much. Doing his job at one of these would be awful. My dad does luncheons and theater and television, but this is like just got to be so tedious. It's funny because Mara was like, well, maybe you ought to maybe you ought to do a light version of the slides in case it's hard to read. And I was like, yeah, I should totally do that. And then did not do that at all. Yeah, that's okay. Half of the room can see that's all you need. All right, so this is where it gets interesting, I guess. Yeah, the avoiding naming specific companies, if you can. No, no. Okay, you don't have to. That's fine, too. All right, so why don't you take over the rest of this slide, I guess. If you want me to try and bring them back now. Let's give them, let's give them until an hour 30. Okay. So until we get down to 30 seconds over here. And then we'll probably have them come back down by one hour. Okay, let's try to bring it back. Okay, so raise your hands. We're going to try not to name specific companies if we can avoid it. Please. But can you all raise your hands, tell me about some bad experiences you've had with APIs and why they were bad? Sure, yeah. So we have in the back, we had a get call used to create data. We've got bad XML up front and documentation, bad documentation. Quit stealing my future slides. Okay, so yeah, that sounds like there are a lot of things there. So creating resources that don't give you the resource back and then you have to make another call to get that resource. So lots of API calls to do one thing. Yeah, sure. Let's get somebody from over here. A lot of, to repeat, just like a lot of baggage, it does a lot of extra stuff. Yeah. Why would that be a problem? So payment system with no sandbox mode. Let's do Michael in front and then, okay, so schema less APIs. I'm sure there are a thousand more ways. We could probably fill up the rest of the hour just talking about things that are bad. But the short version I think of a lot of what you're talking about is easy stuff is hard. There are too many end points. Simple stuff is complicated. The docs are wrong or incomplete. Maybe no wrapper libraries. There are some other things folks said. But yeah, so that's a bad experience. And who, raise your hand if you think you use more, you have more good API experiences than bad experiences. Raise your hand. Okay, all right. Well, that's more people than I thought would raise their hands, but it's still not very many. So today what we're doing, our hands-on design work is going to be using real MailChimp end points. We're going to start by learning a little bit about MailChimp. You can't design an API without knowing the product that the API is going to be used for. Probably really well. And you also can't design a developer focused API without knowing what the developers are going to use the API for. Also probably really well. And with a degree of nuance, not just like, well, they could do this, but more specifically, what is more likely to happen? So that brings us to our advertisement portion of the talk. MailChimp is an email service provider. Our mission is to help people send better emails. And one of the reasons that we have an API is that one of our co-founders a long, long, many years ago, eight, nine years ago, he always tell the story where eight or nine years ago he was at a fork in the road and he had to choose, do I hire a developer to build an API for this new email service company or do I hire a salesperson? Fortunately for me, he decided to hire a developer and currently MailChimp has zero salespeople. So it seems like a good decision. So what are our main features? Lists, campaigns and reporting. Who are you sending to? What are you sending? And what are people doing with it? I guess I... The other thing that we need to talk about is who uses the API. And for MailChimp, our particular use case, there are a couple of different options. There are people who use the API directly. So your company wants to get your own data into MailChimp or vice versa. Our mobile apps are sort of an example of that. But then there's the case where you might have data in a third-party web service that you want to communicate with MailChimp. Say your CRM or your Shopify shop or whatever else. And so our API also enables that level of communication where the user is not... The user might not even know that an API call is being made, but on the backside there are a ton of them. Usage patterns, that is roughly... That's about a week worth of API calls to version two point over API and that's how they break down. The overwhelming majority is list management, getting people on the list, getting people off the list. Reporting is a close second. And then campaigns, which is probably the biggest thing that MailChimp does, if we didn't have campaigns, like what would we do? Almost nobody uses that through the API. And so you have to kind of... I have to ask myself, is that because that's just not something people want or is it because our API is so bad that they can't? So if we're going to look at API 2.0's list management endpoints, what we saw is that is the most important, the most traveled part of our API. So we've got these end point lists that we're going to attempt to hand out. Right, so what we would... Ideally what you'll do is in a minute we're going to go over the list management, like in a little bit more detail what list management means at MailChimp. And while we're going through that, keep a hypothetical company in mind. It could be your own company. It could be one that you've just made up. So for example, we'll give you some examples of an online store that sells pens and pencils and such. And then once you're done thinking about that, you'll have some time to chat with your neighbors. And the reason we did a printout instead of a web page is because last year the Wi-Fi was not sufficient, but this year I hear it's great, but there's still no web page, sorry. Paper. So yeah, so we'll talk about list management and then we'll get to the meat of showing you our dirty laundry here. So we have different parts within a list. You obviously have to be able to edit a list. So we were talking about adding people to lists, removing them. You also, we have merge fields. Merge fields are arbitrary data that are set up at a list level. And then we also have interest groups, which are Booleans like, favorite color was one example, doesn't really. Yeah, and you can set those up. So merge fields might be like a first name or the last time they bought something from your store. An interest group is a little bit more of like they either are interested or not interested. Managing subscribers is another big one. Getting people onto the lists and off of the lists and keeping those fields that we just previously talked about, keeping those up to date. So did you change your name or did you just buy something in the store or have you decided you're no longer interested in colored pencils? Segmentation, once you have them on the list and you have all of this data about them, you then want to use that to send different emails. So you want to send if somebody's bought a lot of pencils, maybe you want to send them an email about a pencil sale that you're having if that's a thing that happens. And then once all that's done, your boss wants to know about statistics and reporting and who's opening and who's clicking and what links and all of that. So that is MailChimp's list management in a nutshell. One thing I'll say is that we do have... Don't go from this talk and then go try to use our API because we're leaving a bunch of features out in the name of simplicity. But so I guess then we have to talk about what's our intent. So among yourselves with your hypothetical companies in mind, let's talk about what sorts of things might you want to do with the API than as your hypothetical MailChimp customer. So let's take two minutes and talk about what the big things are and then we'll come back and chat about them. So go. Maybe I should get this side dimmed at all. I don't think they've managed to do that yet. At last when they were doing a lot of really good deep dye and really good examples. So hopefully that'll keep up. I think if you're here you probably are frustrated. You've got some reasons. If anyone here or how many people here have actually worked with the RAPI. That's a good question. I do a lot of hypothetical research studies in my mind where I just wonder about things like this. Should build an app. Yes. You would have it at the conference and it would send a push notification like because you're in this room or whatever. I guess maybe another minute they seem to be like. There seems to be chatting for those two who are chatting with their phones. That's okay. Maybe they're bad at personal interaction. That's fine. I do that sometimes. Tech people I'm in the room with. Long week and it's Tuesday. All downhill from here for me. Well our senior design presentation looks like the app actually looks really good. As long as you only do the features that work they work really well. There's a couple of things that they look like they work but they don't. Three steps down the line you're gonna not be able to get any data but that's okay. How much of that is like free-range like will your professors be like oh fuck this button. They're not gonna know. We just stand in front of the whole class and we've got our preset demo that we're gonna do and we know that this building works all the floors. We know where the bathrooms are. We know that the dots should appear in the right place. Nice. We were doing edits this morning and one of my group members was like y'all. Y'all we are presenting very soon. I need you to finish. You're making me nervous. All right all right let's let's finish it. Let's finish it up now if we can. Sorry I know I'm interrupting a lot of you mid-sentence. But if you could just. Okay all right let's let's try to finish it up. Thank you. All right let's let's talk about it. Let's share with the group what sorts of things might you want to do with the Mailchimp API. Who knows a thing. Nobody knows a thing. Okay you might want to send an email. That's a really good idea. What else might you want to do. Newsletter. Okay what about for like list management stuff. Yeah okay great that's a really common use case. What else. You want to repeat that so. Oh yeah sorry. Sorry yeah sorry I'm really bad at that. When somebody at his company's store buys something they then get registered on the Mailchimp mailing list. Hopefully only if they check a button that says I want to be on the mailing list. What else what else might you want to do with these merge fields or or or any of that. Okay yeah okay what do you mean by that. Okay sure we typically recommend that you not have more than one list in the first place. There are some use cases where you would want to but we tend to we try that's what we have the. Interest groups for so and the segmentation so what you would typically do is have both of those lists on one list and then when you want to send an email to just part of it you would segment it off for that one email but definitely a use case that that some people have when they have multiple lists for sure yes that's right okay great so being able to set somebody's interest groups as you subscribe them anybody else can yes sure yeah so the the merge fields being able to create those merge fields or create the interest groups through the API that's especially useful like you were like I think you were alluding to if you create a new category for markers maybe adding an interest group for that automatically as the category gets created in your store sure so like their internal your your internal right so adding your your app's local internal ID to their Mailchimp profile so that you can link those up when the data comes back say through a callback or whatnot okay let's see let's some see some of the other things I think we've covered almost all of these and so now what we're going to do is we're going to pass out these end points these are just list management and just version 2.0 and what we'll do I'll come and cycle these around and just take a few minutes look over it and figure out what might be hard what what about these calls either hard to learn or hard to use or or anything like that so give us just a second we'll get these passed out yeah so while this is all going on just take a couple minutes look through the through those end points and see if you can find any problems don't be shy we know this is bad sure like what's what's bad about it yeah like what what might be hard to work with or otherwise use understand like what's confusing all right so that the handout took a little bit more time than I was hoping so let's go ahead and let's talk together about what what's wrong with this and again don't be shy feel free to be as brutally honest as you need everything is a post everything is a post it's restful though right what else what else is wrong with it right so a lot lots of end points so many end points what else oh and he said you could the static segments and dynamic segments could really just be one set of end points what else the API key is in the body of the request that's bad ish right so there are a bunch of other end points in the API that are propended with campaign or whatever so that is maybe more of an more an artifact of of our right so so no context so as documentation the handout is really awful and I'll give you a hint the the documentation on our website isn't much better in the back right so possibly the subscribe and batch subscribe could be the same endpoint that just takes more than one thing yes sir right and aside from it just not being restful what's hard about verbs in the url right okay great so we'll talk a lot more about that in just a minute what else right so a lot of parameters for what should be a really simple call okay let's do a couple more what else do we have yes sir right yeah how do you what air what happens with errors I still struggle with that to this day okay interest group versus interest grouping we're we're renaming that in 3.0 for exactly the reason you describe yes sir right right um right yeah so uh there there's just some random hard limits in the activity um in the activity endpoint where it's like oh it's 180 days well why like why not 30 days why not 70 days yes ma'am right so the batch subscribe endpoint has a lot of like you human figure out how to scale this yourself um whereas we should probably do the scaling for you or just set a limit at a place where we know we can handle the volume so those are all really great and we could probably talk about what's wrong with this for hours I know I have um we do so so many methods API key has a parameter inconsistent naming um how do you update merge fields lots of just lots of like it's just hard I mean it's two pages to describe how to subscribe somebody to a list so let's talk about the principles of developer driven API design um there are only in my opinion really two um you need to design for intent and you need to limit your API's mental footprint how hard is it for somebody to load the API into their own brain so what does that stuff mean so if you look at this like if you're thinking about what Google has in Gmail right maybe you you you've got conversations and then you have the individual messages in a conversation right um and you could set those up in a variety of different ways you could make them completely separate calls you also there are things you want to know to make this particular screen happen so if you know that your intent is to make Gmail you know that you want to be able to get the subject but also of the subject of the conversation but also a snippet of the most recent message and making both of those calls every time for every email could be really a pain and a lot of extra things to do right you you end up with an n plus one querying situation where you have to get the list of conversations and then you have to make a query for every message when you design for intent you put that message in the first list that it's only one call to get the whole inbox that makes everybody's life a little bit easier um so look at this for a minute and tell me if i don't i mean try and see if you can see what's weird about it um so that there's a light there for the air conditioning and the light is on but the but the thing underneath the light says ac off so the light is on when the air conditioning is off which doesn't really make any sense you're not gonna you're gonna look at that and say oh the air conditioning is on because the light is on because that's the way everything else works ever but no that's not how this one works right so if you live in Atlanta a light that tells you when your air conditioning is off in the summer is probably like how you might design it from the beginning but people who've gotten into your car have gotten into a million other cars and they're a lot well that's maybe an exaggeration they've gotten into a lot of other cars in every other car when the ac is off the light is off and so in this way like you don't want to be blazing new trails with your api most of the time um so follow don't lead use ht basic off if you can if you can't use a lot and use whatever version of it you uh works easiest for you accept and serve json who can think of a reason why you might not want to use json there are a couple yes sir in the back right so use cases you might need to serve xml um you might also not want to use json if you've got a ton of binary data um turning that into base 64 and code you might so there are reasons but start from the default of accepting and serving json uh make your api as restful as possible and we'll talk about that in a little more detail shortly um going along with the mental uh mental footprint of your api abide by the principle of least astonishment use your htp methods properly use your htp response codes properly and as a call back to uh what a gentleman over there mentioned earlier please don't ever do that please you've got a 200 okay response code and then a success equals true please just just don't um that should be a 400 or maybe a 500 who knows who knows what's wrong with it it's just not successful um and then if you take nothing else away from this talk about developer driven api design please remember this don't be clever one of the biggest insults that somebody can give your api is that it's clever um it needs to be accessible it needs to be easy it needs to be simple um clever save that for i don't know when but please not for your api clever becomes confusing right and you want to be able to not read every documentation that has ever existed right so let's talk about right so think about if you have a i'm trying to think about the cleverest thing i've seen in an api um a lot of it comes back to using the standards properly um you could be clever by choosing like a really like oh i'm going to use like 422 as my response code because like the description of the 422 sounds sort of like what's going on um i don't know what 422 is i use like 48 what's that right um so that's maybe a bad example that might be a good one um there are so there are there are some hgp response codes for example that mean is something very specific and if a client is uh following the hgp spec the client is then supposed to do something else uh right like oh well you um a good example of the the opposite of that is um if you tell somebody the method isn't available um it should return um the what methods are available in the headers um so you can imagine situations where you just don't want to do something that somebody is then gonna have to read documentation to figure out um and especially you don't want to do something that is clever that like somebody might think it does something else entirely because of the context that they're in but really it does this other thing um i'm sure other people have examples of of uh of cleverness in apis that is painful probably even in male chimp's own api um uh but we can i can we can talk about that a little more offline after the fact a few and i can think of some better examples maybe um so let's talk about rest so rest is an architectural style it's not a standard um it was coined in a phd thesis um and the the worldwide web is living proof of the power of it that's why it works that's why we can do all the things that we do with it so if the worldwide web worked like apis do um trying to figure out where to go for lunch after this talk uh would probably i mean you of course what you would do is you would pull out your phone book and you would page you would turn the page to yelp incorporated and you would call yelp incorporated and you would say hi yelp um i really need to make a search on your website so um could you give me a list of the the data you have available and how to access it uh and some nice person on the other end of the phone would say sure here are end points and here's how you get them uh and then you would think say thank you you'd hang up the phone and then you'd open up sublime text or adam or whatever you're using these days and then you would write a client a web client for yelp's website um that is how we write every api client ever but rest helps the web make it so you open up chrome and you go to any website anywhere and it works uh and so when people ask us oh why rest that's why rest because uh the network benefits of everybody doing the same thing are huge uh and if if it did work like that your desktop on your on your laptop i would look like the desktop on your phone if you were to click yes to every time some website asks you to install their mobile app instead of going to the mobile site so xkcd to the rescue there um so htp at a glance so um http they there are just a few methods right the that's kind of the point you've got you can create things using using post or put um you read using get you can update using patch or put um depending on the implementation and then uh delete is pretty obvious use delete the response codes are also preset for you you've got your success you redirect your and your error response codes and this is sort of what we were talking about earlier is that you should return the error code that goes with the error that's happening or the success code if it was successful um and not try to just try really hard not to mix this up because it's not helpful right um an example here of cleverness that just came to mind uh there's actually a 400 error that says you are making too many calls too quickly um but with 400 and 500 the the general uh idea is that if you get a 400 error you shouldn't repeat that uh call if you get a 500 error try it again later um so you might if somebody is uh over using your api and blocked you might think oh it's clever i'll send a 500 response code back because that'll tell them um you know try again later when you're unblocked but 400 would be far more uh descriptive and would help them to understand oh i'm actually doing something wrong here it's not the service service that's broken so that's that's just one example that came to mind um so rest is a an architectural standard it has six constraints um many of these you get for free just by using htp properly uh the client server model the stateless server um cashability and layered system those are all basically if you're doing htp properly you get all those that's just wipe your hands you're done um code on demand is what enables java script and java applets and um whatever it was that microsoft tried to do active x components or whatever um that's the code on command part of uh on demand part of excuse me uh part of the spec but the thing that really like the reason we're here uh is the uniform interface um that is the part that makes uh that makes or breaks your api really so the uniform interface constraint uh you can think about it in four different ways resource identifiers everything should live at its own address and that is that's a it's a uh it works for developers because we are all well accustomed to file systems uh we're well accustomed to things to our files living in certain places uh and so it it helps people understand your api better because it's something they don't have to learn all over again if you look at mail chimps uh list apis uh you have to learn every single endpoint just to figure out what anything does uh resource representations is the idea that a resource is not the same thing as its representation um so one example of different representations is you might serve xml and you might serve json and it might be the user's choice as to which one which representation they request um you could have different language translations as different representations uh you could even even have different representations that do have different fields in them if you really wanted to um so and the one of the biggest parts one of the places where uh your api will fail to be restful if it if it fails to be restful is in the self-describing message portion um typically and what uh royal fielding recommends is that if you are going to have a self-describing message you should register your own media type with the ian a and you should do that and that media type should describe how to consume your api uh messages um we haven't done that for version 3.0 of mail chimps api yet um in part because it's still on flux uh but also because if you've got to go read that media type i mean you might as well read anything else um and so uh we use json schema and we pass back a link to the json schema that describes the document that you received in version 3.0 um api 2.0 fails because in order to understand the response that you get back you have to go read a giant page of documentation that tells you whatever field is and how to process it and then hypertext as the engine of application state this is what enables the worldwide web for you to just go to yelp.com and then eventually find a restaurant to go to lunch uh at which to go to lunch um and in api's this is sort of a this is sort of a controversial uh thing uh the idea of how to us in an api is that when you you could find anything in the api by hitting the root of that api it will give you back a list of links that you can navigate um from place to place just like a website um paypal's api does this actually um the problem that you have with had us if you if you abide by it strictly is that you have uh it's a lot of calls then to trace that api all the way back to the you know whatever sub resource you're operating on every time you need to make that call um so in version 3.0 our api we have had us links we do not expect you to trace them every time you have a deep call to make we expect that you will bookmark a page inside of bookmark a page to use the metaphor uh inside of our api but the links are there for discoverability um it means that you don't have to read a single page of documentation you get your api key you call the version 3.0 root and you can then navigate and see everything there is to see um if you add in reading a couple of json schema documents you can actually figure out the whole api without hitting our docs page um and that is what uh a restful api looks like um the richards richardson maturity model um describes this in a slightly different way um so if we start from the uh from the bottom you've got plain old xml um and then the resources and the verbs and it's not until you get to the verbs and the hypermedia controls that it's actually starts to be actually restful right if you just have xml or you just have xml with resources you're not you're not restful you have to have the verbs and the controls at which point you get to this magical rest thing right and this is this is not to say that rest is the only way or the best way it is probably the most commonly understood among web services today um and so having a restful api confers a lot of benefits um but maybe maybe this isn't you're sitting there thinking this is just not what i signed up for right i i just i did not want to spend an hour listening to people blather on about rest um but it's important to understand if only so that when you release your api finally and some smug developer on twitter goes well that's not really restful you can know how to respond you at least know what they mean when they say that and you can maybe say intelligently well we decided to deviate from rest in this way because of x y and z use case if you don't ignore them which is what most people do sorry um so let's get let's get down to business let's let's fix the mess that we handed out to you earlier um and just to reiterate the disclaimer you are not seeing the entirety of the mail chimp system so don't if you're watching this on confricks later or you all don't immediately go then try to make api calls based on these docs or anything because it's just a subset um so let's go back in order to design this api we have to think about what the intent was um so if we we've got to remember our tent was to get customers on to our list keep their data up to date um organize our lists send things and also have stats to make our boss happy so we know what's going on um so is there a good reason not to use rest for this list management endpoint can anybody think of one no that's I think I think that's the right answer in my opinion that's the right answer there's no good reason not to use rest for the set of endpoints so um where would we start just no need to raise your hand just shout it out where would we start making this mess restful okay what might the resources be okay a subscription could be a resource a list list subscription what are the resources anybody shout them out list member would be a good one you could subscribe then by creating a list member so that's another option to having subscriptions as its own resource interest group um and interest grouping I guess if you're going to go that route um any what else what other resources might one have a user yeah in the larger api a user might be a resource um okay well we've got some other things we've got static segments right that should be a resource a report uh right so yeah the stats of like the different reports um could each be a resource uh right yeah so you there there's there would be an entire way to manage uh campaigns or emails uh as their own resource um uh you would also uh we talk about merge merge fields those would be a those would be resources on the list right uh but there would also be resources on um each individual member then they have their data the data values of those things um and so depending on how your use cases are you might actually have uh you might actually have a a sub resource on each member that shows their merge fields or shows their interest groupings interest groupings being the other so all right so take uh take a minute and um and talk amongst yourselves about what uh we once you have those resources um what I want to know is how if you were trying to subscribe 300 people or 3000 people or 300 thousand people to your list what would you expect that to look like um what calls would you expect to make um on our hypothetical brand new api that we've just designed in our minds what what would you expect that to look like so take or if you know does anybody know off the top of their head how they would want that to look right now okay good um so what might be the reason so I know when I was talking earlier about having uh or when Kate was talking earlier about having all of the um data available in one call I've got I got some dirty looks from somebody over here on the side of the room what might be a reason why you wouldn't want to do that okay sure so you might have some scalability issues with pulling all that data and sending it all what are there are there other reasons you might not want to do that just send anything everything back sure sure uh that's that's definitely true um right yeah that's great so if you're doing batch processing you have to have a sane way to handle errors um if you send a hundred thousand uh subscribers and three of them have errors well how do you how do you deal with that okay what uh did you somebody up here have one I thought I saw a hand yes right um and so uh why why is duplicating functionality in your api potentially problematic right sure uh so you might it might just be confusing if you have uh if you go totally overboard on designing for intent um you run the risk of creating too many endpoints too many different resources that people have to learn um and that's where the sort of the trade-off of this design happens uh if you don't go overboard with designing for intent then you end up seeing the opposite problem which is to do one thing in your mobile app you have to make 14 queries uh and um your mobile developers come to you and yell at you because your api is requiring it was just too slow um yes ma'am what did you say sure read read conflicts write write conflicts um if you duplicate the functionality and then you've also got just the implementation detail of like if i've got three different pieces of code doing this you've got to make sure your architecture is such that you're not copying and pasting code all over your api um so that two page that two pager that you've got in front of you um if you follow restful principles uh and we talk about the the resources we just talked about with lists and uh segmentation and and that sort of thing it can be summed up like this you can end up with what is that six a half dozen resources that you can operate on using very basic uh HTTP uh verbs and you end up with a far easier thing to understand now there's still the issue of what parameters are passed what um what data comes back and all of these so this isn't the full documentation obviously uh but i hope that you'll all agree that if you see this this is far less daunting and far easier to um understand and navigate than the two page like 10 point font like mess that i handed you that we handed you at the beginning so that is um the gist of it um we are getting very i wanted to leave a lot of time at the end of this for questions because i figured you would all have very specific things um and so we're going to talk very briefly about um how we worked with api version three um uh both evaluating it and then some of our implementation details and then i'm going to leave a lot of questions for you to ask uh for your own things because we understand that this worked for us um but you might be having a problem how to how does that map onto your own um implementation so um um so so this is how we discovered that 2.0 was a mess um and so it doesn't look sketchy i'm just going to announce that you're leaving kate has to go she's being given an award by her university since she has to actually go receive it so um thank you kate um so we got direct feedback from our users um we looked through our support requests uh we had a ton of them uh we looked through social media complaints um this sucks i'm having a hard time i don't understand mail chimp and sometimes those were user error and sometimes those were mail chimp error uh we actually sent out surveys um we found people who were using our api especially the other web services that were integrating with mail chimp uh and we looked through we asked them what's hard about it uh and because as we sort of saw earlier most of you have more bad experiences than good experiences uh with apis excuse me the poor user experience on an api is the default so in my opinion if people don't love your api it's probably not very good um mail chimps api is not very good and it was relatively well received 75 percent people thought it was great or excellent so um when you're getting this feedback keep it in that context that if people aren't over the moon in love with it there's probably a long way for you to go to get ahead of the pack um and the pack is not in a very good place right now so you definitely want to be ahead of it um hints from usage patterns really really important um collect data log everything about your api um it sounds hard especially when you start doing volume but it's really important uh that you keep track of every call and as much data about that call as you can um excessive calls to certain endpoints uh relative to the customer size for example if we have a person with a 600 member list um and they're making 600 calls a second there's probably something wrong and that thing wrong might be that they don't understand they've made a mistake they don't understand something about the api it could be that we're not enabling a really obvious use case that they need um underutilized endpoints for key features like our campaigns uh high error rates on certain endpoints or for certain users can sometimes indicate that there's something confusing about that uh and then really common but oddly specific queries so if for example you see the vast majority of your queries to a certain endpoint include the same sort parameter maybe that ought to be the default um so think about that and and above all when you're looking at usage patterns collect as much data as you can I just be curious browse through it every once in a while search it in different ways try to have some kind of easy easily usable dashboard we pump all of our data into elastic search uh and then have um a nice dashboardy kind of thing on top of it um and so that really helps us to see error rates and sort of pair things down differently um and then above all when you're looking at this data start from the assumption that your users are not idiots some of them will be but assume that they're not to start with and that will get you a lot of information um even people who are doing things in what you think is a stupid way it might be because that looks like the best way from your documentation or from your endpoints and then a couple of rules of thumb we have for for bad api design um the best way for you to find these out for yourself is to code against your own api eat your own dog food as much as you can uh and if you don't have any internal need for using your own api somehow make some sample apps like do the work uh do you have to make frequent references to your own api documentation um I do when working with this is what I do every single day is work with the mail chimp api and when I write code against version 2.0 the api I have to go back to the docs a lot and that alone is enough for me to say that we've made a lot of mistakes if you find yourself copying pasting from your examples a lot maybe the example maybe the api maybe the wrapper library you have is two verbose um long argument lists are often a hallmark especially in wrapper libraries and then if you ever take something out of your api and immediately every time you get it turned into something else then that's probably you have a bad representation of that data somewhere um so for example in one previous version of our api we have a merge field called address um that you can use it's just a data type it has you know address one address two city state postal code you you know you know the thing um and at one point we were actually serving it as a two space separated string all of those fields jammed together in that order um and so what did nobody in the world needs the data in that format and so you would get it out of the system and then you would immediately exploded on those two spaces and then hooray I've got the thing I actually wanted um so that's one of those where you if you just start using it you'll start to pick up on those patterns pretty quickly um and then some things that you you can look at for your own apis um we use json hyper schema to define the api define all the endpoints um define how links are served for hadios um it's uh currently making its way through the standards bodies it's not a spec yet but um hopefully one day um we are looking into both swagger and rommel we haven't really made a decision yet but hopefully when we launch we'll launch with one of the support for one of those two um if you are using something like json hyper schema you should be able to doc like you should be able to use that to generate wrapper libraries to generate documentation um and one really easy way to start finding problems with your uh with your documentation sorry not with your documentation with your api is how hard is it to write the the document the auto generator for the auto generator for the documentation um if that becomes really hard then maybe think about why that is um if it's hard for you to write a program to understand your api how is anybody else going to do it um and then make sure you have uh ramp wrappers and sample code um in our in version 2.0 our sample code are actually apps like we have a rails app i think it's still on version two three or something crazy um we have node app we've got all that we've got apps for all these different languages which first of all that's not what anybody wants to see right like if you're trying to use the mail should pay pi you don't want to see a rails app like you want to see the code that actually interfaces with the api um and also that it becomes a nightmare to maintain um and so uh try to keep your sample code easily copy and pasteable get rid of as much fluff as you can um you don't need to give people examples as we did on how to build apps just show them how to use your api um and then make sure that you're thinking about catering to different kinds of learners um some people want to read the docs so definitely have docs some people want to just play with your api um so uh if there's time at the end i can show you the sandbox that we built that auto updates based on jason schema but you can just browse our version three of our api um and then just sort of think about how different people are going to learn your api and then um you know architecture and scaling concerns those are things that you just sort of have to learn in the hard way um eventually somebody is going to use your api in a way um that you hadn't anticipated and they're going to be calling a very expensive call frequently at a high rate and it's going to take something down and you just have to figure out figure out a way around that but if you know already that you're giving up data that's expensive find a way to cash it find a way to limit access to it find a way to keep it from becoming the default um and you can maybe try to avoid some of those outages so we've got if i am reading this correctly we've got maybe 20 minutes left um so let's go ahead and take some questions uh and we have enough time that we can get pretty deep into some of these so yeah um so the question is let's talk about authentication um signed requests my now my experience and knowledge of signed requests is much more limited than a basicoth but where i've seen signed requests most useful is in um single like if you're using it if you're using your api as a front as if you're doing the thing uh dhh doesn't want you to do which is rails as an api and then put a javascript mbc on the front my understanding is that signed requests really help with that aspect um but signed requests if you if you think about the reason why i love basicoth um for apis if it's possible is that the amount of time that it takes for a for your new user to go from i want to figure out who's on my mail chimp list to i now have a call that demonstrates that like you can do it in three lines of code right you you pull open htp party or if you're using python you pull open requests you hit one endpoint boom it's done all of those libraries understand htp basicoth at a fundamental level you can even do it in your browser with the you know username at api key or username whatever it is with the at sign before your url you can you can do that in the browser so htp basicoth if it works for you is amazing because it's supported so widely in so many different tools um there are times and places for other things definitely evaluate them all but um if you can support multiple kinds of off that's also good absolutely um that's a great question so in version 3.0 of our api we deviated from rest uh in in uh one specific place i think and i i don't i'm not entirely sure if this is actually a deviation or if it's just a deviation from what people think of as rest i haven't gone gone through the thesis to like figure it out um but one of the things that people tell you about restful uh apis that you want to get verbs out of your out of your urls get verbs out of your urls well that's great um but if you there are some things that are really really weird when you try to turn them into resources so for example we've got email campaigns um and maybe i'm just not as smart as some other people but i couldn't figure out how to get sending a campaign into like a resourceful architecture that made any sort of sense and wasn't overly complicated just for the sake of being restful um so we follow heroku's recommendation which is if you have non-restful actions basically if you have actions that aren't like htp verbs if you're doing something other than crud essentially um to have an action sub resource and then the action after that so in version 3.0 of our api if you want to send a campaign you go to campaigns slash the idea of that campaign slash actions slash send and you post to that url um and that's one of the biggest places we do that in several places uh where it just doesn't make sense so like you could have like a send's resource that you then create one of um and we thought about that but that to me seems a little contrived um and maybe maybe some of you disagree with that but we thought it was contrived so we're just like ah send it's it's rpc but we need it for this so that's one example sure um yeah and and if we had uh we don't have um right now we don't have a tremendous level of introspection into our delivery side um from the web app so like we don't know how many have sent in the web app um delivery knows that but we haven't pulled those apis together yet but yeah that's certainly i mean i'm not saying there aren't ways to do it um but since you can only send a can and this is maybe a feature of our of our product you can only send that campaign one time ever if you want to send it again you clone it and create a new one and send it again so in that way like there would only ever be one send request hopefully and when you're at that point it's like well okay like for us we just thought it was better to do the the action send i haven't actually um facebook uh api is a scary thing to me and i don't have to touch it every day so uh no is there like a specific thing about it that you're curious about that i could maybe it sounds awesome um it sounds really useful it also sound i'm sorry yeah so he was talking about how apparently in the new facebook graph uh query language you can compose different uh and get different resources returned in one request i think almost that that sort of thing might also be made very easy by something like web 2.0 or a htp 2.0 um not the exact same thing but it might enable it a little bit more easily send off three or four requests at the same time get them back that sort of thing um yeah so there are so when you're versioning your apis there are a couple of different schools of thought one of them is and many of these schools of thought are very like people feel very strongly about it um we version in our urls um to me that's the easy that's the most straightforward way um another way is to version in your media type um so in your request uh your users would send an accepts header and the accepts header would include the version in it saying hey we're here we're ready to accept version 3.0 of your api um to me that's a little bit more dense it's a little bit less clear for people um it might be a little bit more semantically correct um but from for from my perspective um sometimes the semantically correct part makes things hard on users and saying oh well your only give you the example what will inevitably happen if you only version in a header is somebody will write code that doesn't do versioning at all they'll write code against version 2.0 of your api you'll upgrade and since they're not passing an accepts version header you'll be like oh you must want the most recent version and then you'll pass them 3.0 break their stuff they'll complain on twitter and your boss will be like why people complaining on twitter um there are obviously ways to avoid that if they don't send a version you send an error back but then we sort of get down that rabbit hole of like well why might not just have a different endpoint entirely which is what we decided to do um so Heroku's design guide is basically like use rest um and uh the the qr code on the top of your handouts there has a link to a whole bunch of different uh links that I used in the uh designing this presentation so Heroku's guide is on there um some other api design talks as far as when not to use rest right right what to do when you can't avoid it I I think that um Heroku's is pretty good and I in a certain sense uh that's not really my area of expertise um I I think that at least right now um the the benefits you get from rest in terms of hdp caching and uh different cds like akamai being really easy to work with if you're using a restful api not being quite so easy to work with if you're using xml rpc or soap um I and I think that just like with as many people as are using rest right now or at least trying to use rest right now um it's hard to blaze new trail now if somebody did and it was amazing then maybe five years from now we'll be sitting here talking about why would you ever use rest anymore nobody uses that and that'll probably happen at some point but I think right now I haven't seen a lot of good and one of the reasons we went restful is because we I couldn't find a lot of good reasons to use xml rpc or soap or any of those so um sort of uh we have uh in in almost every case we have um we we use sub resources so you would go lists id members email hash to like find a member um we don't necessarily have a documentation of like oh well this member has been sent these campaigns um but we tend to try to make it as hierarchical as possible so that when you are down in a member um you can get things about that member uh and so we try to keep it related that way instead of trying to define a bunch of oh well this campaign has a sent to uh so that's maybe a good example if you look at if you get the collection of members that have been sent to on a campaign um we tend to provide those member resources inside of not inside of the request but if you go to campaign slash id slash or maybe it's reports slash campaign id slash uh sent to I I'd have to look at the docs to be 100 sure but um that will provide you a a collection of member resources that are the member resources from the slash list slash members endpoint um and when those have their hadio slinks in them they point back to the canonical representation of themselves back over on list slash id slash whatever so the answer to your question is not really but sort of that's a good idea so documentation show shows sort of like a top-level system architecture diagram of what your resource how your resources relate to one another well let me tell you so okay so I first have to tell you our dirty little secret and that's that mail chimp is a php app um sorry but let me tell you how we um so let me tell you how uh we do it in versions prior to 2.0 and that is when you create a new version um you open the directory of the previous version um you select all I bet you know where this is going don't you uh you copy and then you edit the code as appropriate um I don't like that uh way of doing it but that is one way um we found that to not be scalable for all the reasons you might think it's not scalable in that oh we found a bug in version 2.0 well I guess we better make the change in 2.0 and 1.3 and 1.2 um in 3.0 we've completely changed the architecture entirely to support rest of like basically the top the bottom or top level of the api whichever one is the most basic um and so what we'll do when when we inevitably has version to 3.1 uh is we will have our um router at the top level fall back so if if you request version 3.0 slash lists and we haven't created a version 3.1 of lists it'll the router will know to fall back to previous versions of the api um how we will implement that is yet to be determined because we don't have a version 3.1 but um eventually that is our goal that until a resource actually changes there's no need to version it um and then once we do need to version save lists does change in 3.1 um theoretically many of it much of it will stay the same and so we'll be able to inherit from um version 3.0 and just change what's different um so those are those are some thoughts that we have on moving forward uh and on what was bad about the way we did 2.0 okay so the question was how do we do our documentation um how do we make sure the documentation stays up to date with the actual app um we'll do a an old and new in version 2.0 uh we actually generated the documentation from comments in the code um we also did this crazy thing where our um the api as it was parsing the request would check against those dock blocks using reflection to make sure that your code was your your request was appropriate so it was the right types and whatever uh which led to a very interesting conversation I had with a coworker of mine in which one of us said oh man we broke the api by making a bad comment there we're really gonna have to put some unit tests around those comments um if you ever find yourself saying you need unit tests around comments you have made a wrong turn somewhere um so uh so but what we were doing is on the documentation side it's less crazy um but you still do end up with the the problem of of of having to um um sorry lost my spot uh of having to keep those comments up to date uh we use json schema at the renderer level of our api so the first thing you do in our version 3.0 uh when you're creating a new resource is create the schema um and the schema will have title and documentation title and description uh data type and all of this information in it and the renderer will use that uh to generate the um generate generate the response essentially sort of at a deeper level the the controller the resource returns some data uh data object the renderer looks through the schema and says okay let me pull uh this response this uh this request needs to respond with a title and or a name and an email address and whatever else and it goes and pulls that data out of the data out of the data object that was returned and constructs the it it serializes it but it builds the serialization it it starts with nothing and adds things from the other doc and or from the other data object that comes back and what that allows us to do is is it means that unless something is really really bad wrong uh our documentation that is built off of json schema will always match the stuff that comes back because the renderer is building that exact thing from the schema in the first place um and so we sort of fix that problem by forcing you to design the schema and keep the schema up to date because the schema is what gets returned and so that's that's sort of our that's that we had that exact problem where it's like well we have to update these comments and all this and so we just said no like design the schema first design the code to implement that schema later and then it all so far it's been working out pretty well and then we use that json schema to generate documentation right and I think swagger actually sometimes you like uses json schema to define the resources so um so the question was how to how does mailchimp determine what um what the people are using the resources for and and for this we don't have a very technical approach um because most of the api traffic we get is from those integrations those third parties that are making requests on behalf of one of our users um we ask them um and we try to open those lines of communication so that they know that if something is hard or confusing that it shouldn't be and that they should complain to us and that from the volume of complaints we can sort of generate that um if you keep a lot of stats about your api you can sort of start to intuit things um but I I don't have a good technical way I think that a lot of it is just keeping lines of communication open with the people that are using your api and listening to them when they say they want something um I don't know if anybody else out there is like this but I know my first reaction to ah we need this new features you don't need that feature is feature this is perfect the way I wrote it the first time and so I have to fight that internally um but it's really important that you do fight that because sometimes when they say I need this and you're like well that breaks the purity of my api it's like well yeah but what is your api if it's not useful to people so so tools to maintain the the documentation um okay we're five minutes over then I don't want to cut into your break um thank you all so much for coming if you have further questions um please come see me