# Design the Uber API Whenever answering questions like "Design the `<insert service/product here>` API", you want to make clarifications on what exactly we need. ## Clarifying Questions Uber is a big product these days with many sub-products, so a good first clarifying question is: `Are we talking about the taxi service?` Uber has products like Uber Rush (delivery service) and Uber Eats (restaurant delivery) so we want to make sure that we are scoping the problem well. These problems are super vague for a reason. I mentioned that we are talking about the Uber Taxi service so, another good clarifying question would be: `Do we care about Uber Pool?` While that would be a fun problem to answer, it's not in the scope of the MVP that we eventually discussed. If we had time, then we could discuss how the pooling service would work. ### MVP Discussion Before we continue, we should talk about the MVP. Once, you've clarified the scope, we should discuss the core functionality of the application. This is where I ask you to recall how Uber or any Ride Service works. **Note**: If you don't remember or don't know, that's totally fine. We can discuss exactly what would make sense. This is where you should be comfortable to explain your thought process on how something like a Ride Service should work. This is where you get to show your leadership and ability to try to think on the fly and work with the interviewer to discuss what makes sense. Think of these questions as collaboration sessions with the interviewer. What would you try to build if you were on the Uber team when it first came out. **An interesting note that popped up with a lot of the interviews I've conducted on this question**: A lot of you talked about logging in. This could act as a clarifying question as well. Some services don't really have a profile (think Transit Tracker). I told you who asked that let's not worry about a profile and let's make the assumption folks can just use their phone numbers to be able to track things. Another note was that a lot of you talked about real time updates, which is excellent. So, the question that came from this the GPS. I mentioned that assume that we have a GPS service built already in the application for both drivers and users. Also mentioned about matching the driver. I said let's make the assumption that that algorithm was created for us already as that would be out of scope for this problem as well. Finally, Uber Taxi has a lot of extra features like reviews which most of you talked about. Again, ask these questions as clarifying questions. It shows that you are thinking about the future of the application and also what a good experience might be for all the users of the application. ## The Core Functionality After we got through all the clarifying questions, this was the core functionality we settled on (this should result from the MVP discussion): - A passenger (one API) goes on their phone and requests a ride - A driver accepts a request - A passenger can keep track of where the driver is when they are waiting - A passneger can also keep track of the progress of the ride as it is happening currently until they reach their destination - A passenger or driver can cancel the ride before it happens ## API Design ### Entities I said to think about how you'd design an API as if you were building it in Express and using their routers. I also said to think about what information gets sent first because when we request a ride, we don't get a driver until a driver accepts. I also said to think about the "entities" (you can think of these like classes). Who are the main players and what connects them? The main players are the Drivers and Passengers and the Ride connects them. We now have our main entities. **Note**: Don't try to add schema design into this as that would be a separate problem and could take longer. #### Ride Entity This is what connects the passenger API and the driver API. The Ride Entity should have this information: - rideId: string - passengerInfo: Passenger Information (see below section) - driverInfo: Driver Information (see below section, but also remember that this information would not be available at the start of the request) - rideStatus: enum (created, matched, started, finished, cancelled) - pickupLocation: coordinates - destinationLocation: coordinates - timeCreated: datetime - rideStartTime: datetime - priceEstimate: money - estimateRideFinshTime: datetime #### Passenger Entity The Passenger Entity should have this information: - id: string - name: string Eventually, you could add ratings in here as well #### Driver Entity The Driver Entity should have this information: - id: string - name: string - vehicleInfo: Vehicle Information (see below) - ridesCount: int Same as above, eventually, you could add ratings here as well #### Vehicle Entity The Vehicle Entity should have this information: - licensePlate: string - description: string ### APIs #### Passenger API The type of request plus what info is being passed in to these requests. These will be CRUD operations around the Ride Entity - POST request: CreateRide(userId, pickupLocation, destinationLocation) - When a passenger books a ride, a Ride is created with above info with a "Created" status. The backend will then call the FindDriver API (that we can assume has an algorithm already written for us to find the most appropriate driver). Once a driver is matched, the backend will call an EditRide route to update the Ride info with a "Matched" status as well as the Driver Info - PUT request: EditRide(userId, [...whatever needs to be updated]) - This will be wrapped within a websocket that will stream realtime driver info to us as well as editing the various pieces of info on the ride - GET request: GetRide(userId) - Could be a websocket connect or something that is requested every few seconds to get a status update when we first request a ride and we are waiting to be matched with a driver - PUT/DELETE request: CancelRide(userId) - Depends on how you want to play this. This can be part of EditRide where you're updating the ride status or you can treat it as a separate functionality #### Driver API - PUT request: SetDriverStatus(userId, driverStatus) - Driver Status would be something like "Unavailable/In Ride/Standing By". These would dictate how the matching algorithm would work. Driver can set themselves as "Standing By" to indicate they are ready for a passenger. Then, if they accept, the backend will update the driver status to "In Ride" (perhaps take them off the map of available drivers). If they are done for the day, they can set their status to "unavailable" and this will take them off the map as well - PUT request: AcceptRide(userId) - Calls EditRide and SetDriverStatus to edit the necessary info (ride status to "matched" and driver status to "in ride") - PUT/DELETE request: CancelRide(userId) - PUT request: PushLocation(userId, currentLocationlocation) - To match with the above websocket with the user who is streaming the location of the driver ## Extra Credit: Uber Pool A few ways to go about this: 1. Allow a ride entity to have multiple passenger information as well as Rides having to maintain a list of destinations to stop at relating to the individual passengers' indications 2. Or create a new entity entirely called PoolRide, which will have a list of Ride Entities attached to it. The only difference here is (that is not seen by the passenger) is that when the passenger requests a ride, and it is accepted, a Ride entity will be created for that passenger but will be put in the PoolRide entity. Drivers would have an extra status to indicate they are in a ride but still will take passengers.