RapidAPI: first steps with Python
By: Thorin Schiffer
Tags: Rest Api, Web Development, Development, API, Python

TECH GUIDE

RapidAPI: first steps with Python

A friend working for a bank told me once desperately: “Why do we pay so much for the IBAN parser? 300 Euro per month? I can’t believe why is this so expensive”. All I had to answer: “I can do it for 50 :D”. He confirmed he would take the deal, and I started researching. Well, deals with business people you know.

My dog likes REST APIs and smelly dog treats.

While looking for special hosting for API’s I stumbled upon RapidAPI — the Andreesen and Horowitz baked API market place company from California. This was it byotch, maybe even this is what I was looking for my entire career.

As a backend engineer, you have fewer opportunities to play a single-player: you can’t design a nice-looking app everyone wants to lick; or a website with outstanding usability, which other less abstract colleagues can. Besides that, no Instagram influencer or a teenager needs facial recognition API. Our creed is, in a nutshell, a B2B service.

The problem is that you usually can’t reach the decision-makers so easily, and a lot of boilerplate comes on top: billing, accounting, security, and whatnot. All of that is done with the app stores for the app developers, for example. And finally, here we are, RapidAPI.

RapidAPI, on one side, offers an API developer a platform, which allows them to concentrate on the essential part of their business — complex problems and new pluggable functionality. The platform supports REST and, since recently, GraphQL APIs. On the other side, it allows the companies to configure the access once and request the service from different API providers over a single gateway with a single key. Quite a charming idea, actually!

The first person is ever known to be charming.

In everyday programming, we fellow devs ask ourselves: should we write it ourselves, or should we use a library? If the library is well developed and could survive multiple releases, then why not! RapidAPI takes this idea even further. Instead of a program, it offers you a service where balancing, SLA, and availability are no longer your problems. Well, at least not all of them.

There is always a fly in the ointment, though: The project is not perfect. Many of the APIs are buggy, and the platform itself shows quite a disintegrated usability concept. Maybe it’s because I’m in Europe, maybe not, but the web apps are fairly slow. Some of the elements are buggy and poorly documented, but that is, I am sure, caused by rapid growth. Pun intended?

FastAPI and RapidAPI

It’s been a long due for a good python mini framework for the APIs to appear. Django scares off the newbies and data scientists by its monstrosity, age, and existential crisis. Flask was never created to be an API framework, and although it’s very slim and pluggable, neither Flask nor Django was created for programming APIs. Although Django rest framework is an amazing piece of software, it’s just not what you need.

Python celebrates the second (third?) coming. With all the new amazing technologies being released, python is the lingua franca of data science. Asyncio has spawned a whole new branch of web frameworks and attracted more interest from the community.

One of those frameworks is FastAPI — Flask for APIs with asyncio, WebSockets, and http/2. All that you wanted. Fun fact: I’ve known about it first from a data scientist I’ve met at Cornelsen Verlag. It is so easy to use, so even non-specialist in distributed systems can start right away.

The framework is incredibly well documented. Everything I needed could be immediately found. Like many other rest frameworks, FastAPI supports the schema generation based on the models from pydantic — a marshmallow competition built on new python typing functionality.

Like this:

class ParsedIBAN(BaseModel):

iban: str

compact: str

country_code: str

bank_code: str

account_code: str

length: int

bic: BIC



class Config:

alias_generator = to_camel

And here is how a typical endpoint would look like:

@app.post(

"/ibans/",

response_model=ParsedIBAN,

responses={400: {"model": Error}, 401: {"model": Error}, 422: {"model": Error}},

)

def parse_iban(iban_str: IBANString, current_user: str = Depends(get_current_user)):

"""

Parse IBAN supplied in the post payload.



ERRORS:...

Quite straight forward and self-understanding.

RapidAPI requires the open API schema file so that this one can be created with the built-in functionality of FastAPI like this:

def open_api():

api = get_openapi(

title="IBAN PARSER",

version=VERSION,

description="Parses IBANS",

routes=app.routes,

)

api["servers"] = [

{"url": "https://iban-parser.herokuapp.com", "description": "Production server"}

]

...

return api

Dump the result in a YAML file like that:

@invoke.task

def generate_schema(context):

"""

Generates open api schema yaml for the api

"""

from main import open_api



with open("schema.yaml", "w") as yaml_s:

yaml.dump(open_api(), yaml_s)

CI upload schema and automatic upload

Create React App Sample…

To provision the API, and at the first place the endpoints, you can upload the schema file over the web interface. This is a quite simple approach but not really compatible with a lifecycle of a modern 12-factor like API. It is a quite common event in the lifetime of an application that the endpoints change, and uploading a schema file every time you need an update is not the way of samurai.

RapidAPI offers a way to integrate those updates in your ci. Funnily enough, over their own API for meta-information provisioning. Unfortunately, the API is quite buggy, and it took me a while until I figured what the thing was. For instance, it returns “204 no content” instead of 200 when all is fine and 400 with blurry error messages. I’ve posted the working curl with schema YAML in the discussions on the API page. Here it is once more:

curl --request PUT --url https://openapi-provisioning.p.rapidapi.com/v1/apis/$RAPID_API_API_ID \

--header 'x-rapidapi-host: openapi-provisioning.p.rapidapi.com' \

--header "x-rapidapi-key: $RAPID_API_APP_KEY" \

--header 'content-type: multipart/form-data' --form "file=@schema.yaml;type=application/yaml" -i

You can find the API id (RAPID_API_API_ID) on your marketplace page, and the app key should be inserted in the provisioning API overview.

Besides that, while trying to guess the names of the fields, I figured that the GraphQL backend requests the same API for the frontend, so you can also update the API's metadata from the overview page, which is not directly configurable from the schema file.

Here is a little invoke task I came up with:

@invoke.task

def update_api_data(context):

"""

Updates rapid api data from the schema file

"""

import requests

from main import open_api



url = f"https://openapi-provisioning.p.rapidapi.com/v1/apis/{env.str('RAPID_API_API_ID')}"



api = open_api()

with open("RapidApiDescription.md", "r") as f:

long_description = f.read()

payload = {

"name": api["info"]["title"],

"description": api["info"]["description"],

"longDescription": long_description,

"websiteUrl": "http://iban-parser.herokuapp.com/docs",

}

headers = {

"x-rapidapi-key": env.str("RAPID_API_APP_KEY"),

"x-rapidapi-host": "openapi-provisioning.p.rapidapi.com",

}



response = requests.request("PUT", url, data=payload, headers=headers)

if response.status_code == 204: # somehow they think 204 is okay

print("Upload OK")

else:

raise Exit(f"Upload not OK: {response.status_code}: {response.text}", code=127)

Rapid API testing

Another interesting part of the platform is the testing engine. For a perfect API, you would probably cover it with unit tests. RapidAPI allows you to monitor and overwatch the API from the outside, combining the integrational testing and monitoring in one tool.

Add and configure tests and their scheduling interval; get notified over email or SMS. And they are annoying too! For free!

And now one more bug: the schedules are not working properly: they would not start immediately but at a random point in time. I hope to see that fixed.

The configuration tool is pretty much self-explanatory. A pretty neat feature is building tests based on your schema file's endpoint descriptions: the parameters and URLs are already there!