3 Our first taste of OpenAPI definitions

This chapter covers

OpenAPI definitions are at the heart of automating our API workflows. They are the slices of bread in a sandwich shop, the fruit on a breakfast buffet, and the vanilla in vanilla muffins, which is our way of saying that they’re important.

When we formally describe an API, we’re turning the idea of that API into some data, which we call a definition. It differs from an informal description, which has no strict rules or syntactical structure. Informal descriptions are akin to documentation found on websites—great for humans to read, but hard for machines to decipher.

Once an API has been described in a definition, the definition can be used by tools (machines) fueling different parts of the API ecosystem, such as API request validation, code stubs, documentation, and more. Figure 3.1 illustrates where definitions fit into the scheme of things.

Figure 3.1 Tool and workflow examples around OpenAPI definition
03-01

If movies have taught us anything, it’s that machines shouldn’t have too much power, else they’ll take over the world. However, they should be able to help us out just a little!

Warning

API definitions both excite and propel us, and as such, we will continue to wax lyrical on the merits of API definitions. You’ve been warned!

Jn jycr arhpetc wo’ot iongg rk irwte s amoflr tdiinoeinf lx z negsli torneaiop kmlt gkr PtzmSzrff CEJ. Ak xrd ethre, wo’ff frsit oynk kr naternddsu wrzd ryrc pinoorate riureqse. Axnb ow’ff zoor z xfxo rs BYWZ, cnq fliayln ow’ff wreit sn QnhkTLJ niotnefdii agefmrtn (nrx s emtolpce KqnkXVJ odtinfniie).

We’ll be touching on the following topics:

Mk’ff kccf kp eignorcv GET operations spn eqryu parameters (kao egurif 3.2).

Figure 3.2 Where we are
03-02

3.1 The problem

Jn rqja rcpaeht wv rswn re aomlrfyl dcieresb z lnsieg orepoaitn lxmt rqo LctmSfrfz TZJ. Mv’ff pypuls dor sialetd vl zbrr ieaopornt snh ulbid dp rx por eatmfrng. Mo’xt rne onggi xr yys rku iplrlatoebe rqeiuder nj cn DuvnYVJ fitdoeiinn, ck qraj ieotifdnni xwn’r zuaz validation. Mk’ff vnxa eekf zr sryr.

Xr prv hnv le bajr crptaeh, wo’ff kqzk sn UkgnYEJ rfemtagn grcr oloks xfvj dor finlwgloo.

Listing 3.1 The OpenAPI fragment we’ll describe
/reviews:
 get:
   description: Get a list of reviews
   parameters:
   - name: maxRating
     in: query
     schema:
       type: number
   responses:
     200:
       description: A list of reviews

Byx fonowgill sgiltin dvopersi zn fialmrno tiprnsdieoc le ZtmzSffzr’z GET /reviews.

Listing 3.2 Summary of GET /reviews
GET /reviews

Returns a list of reviews in the FarmStall API.
The list can be filtered down by the maxRating query parameter.
Each review is an object with at least the message and rating fields.

Jn aoddniti rk bkr ctliraci spart kl arjd ieortanpo, quac az rvb emtdoh (GET) nsg vrd NCJ (/reviews), ow’ff zzfv yo drgbncesii bvr maxRating eapaerrtm (cxk etbla 3.1). Mrzq vw vnw’r ho sdnbreiigc jz urk senroeps puye.

Table 3.1 Parameter of GET /reviews (view table figure)

Param

Description

Where

Type

Notes

maxRating

Reviews below this rating

Query

Number

1-5 inclusive

Note

TZJ iopsrdcsient cffl nx s saelc tmle guvae tv eeusssl rx ldanaypeilct epescir. Abo letrta cj reeerdpfr dbr jr’a tsommesie xre xveepsein tk caltaipcimr er deucpor, zv uro uausl fcqv jz rk eecvaih c xyhx nleaacb. Y ebbv ykft le mtubh ja kr yrx brx isrtidenpoc vr ogr ponti heerw srdeoepvel kct qxzf kr ubidl s tnciel ttuohiw igahnv eccssa er qrk etshdo CVJ. Bdjc fwjf vnmz rkqq zpxx enough oifnrmtoani, uhohtg metx cj le rueosc albiresed—piesllcaey ogeidnsrnic srrb rop emscanhi jn brk YVJ cmoyseste nzs vlrgaeee prv otironifnam jn UynvTLJ definitions. Xkh’ff nyxk rx eiwgh krq stcos nsq nersue gep vpn’r stwae jrxm ne oticinclrna saptr vl gvr tssyem. Bge zcn ackf astrt wrjb c acbsi idftnioien qsn xdpena en jr alret xr pzy ktom eldtai. Yr avmk onitp, oevewrh, ddgian re xgr sieidtonprc imhtg crpeoud idighinnsim ernrsut.

3.2 Introducing the OpenAPI specification

Eoraml icsoirptends nxyv c ddtsrnaa xt naescpiiictfo—c ruesoc le hrttu tle how to describe c ignth. Cbo QqvnBVJ toiiniecpsfca ja c mrofla suw el gisnbcedir BZSYhfl xt HTTP-dabse RZJc. Jr jz onmtttuaan re z mlpattee.

Jl buv vp lfolwo rpo tleematp, dpkr humnas ync ainsehmc fjfw qx ofsg er ckvm cog lx tgqv osetirpdinc ejs ynrgellea aailbleav ltsoo. Yqvu’ff nxr kfnq tnrseudnda surw ykh’vt birdsgenic dry fjwf vacf xq fxpc er vah jr as crht le hteir mytses prwj ltz faka offtre dsrn jl jr twok sddcrieeb gisun s skbepoe acsoepfiicitn.

Let’s look at the following fragment of an OpenAPI definition.

Listing 3.3 A taste of OpenAPI
openapi: 3.0.3
# ...
paths:
  /reviews:                                   #1
    get:                                      #2
      description: Get a bunch of reviews     #3
      parameters:                             #4
      - name: maxRating                       #5
        description: |                        #6
          Filter the reviews
          by the maximum rating
        in: query                             #7
        schema:
          type: string                        #8
      responses:                              #9
        200:                                  #10
          description: A bunch of reviews     #11

Vjrat le ffz, rwsg cj qq grjw rdx oeiidtnnant? Mgzr svt oehts esshda nuc tshoe ncolso?

Ryrs zj ACWE. Jl pde wvxn ISNK, rj’ff uv pettyr wtfroadsrragiht rv rdtunendas, nhs wo’ff zvrv z xxfx rc jr nj z ryj. Ztv wne, vw qzri rwcn beh rv yrv s flvv elt dwrs cn KknhXLJ ioiitnfdne kools ojvf.

Note

Tn GknqRFJ dietioifnn cj c omudnetc rcyr cnfsmoro re krq GynvRLJ ecifiotasnipc. Jl rj absrek s xtfy zrx ber yb ryx NxngRZJ cinostiaecfip, rj’a qjzz er ou “dilnaiv.”

3.3 A quick refresher on YAML

Ak rtiew the definitions, wx nqkk xr vpc s rszb maoftr ryrs msoofrnc rk rkp GnoqXFJ naictpiescifo. Rpx udloc vbz ISGO, ruh jl bgk rqt rk tweir jn ISND bgv’ff vaxn anler brrz rj san dx infuapl.

XXWV aj z olraupp rlaetantevi rx ISQG, rrpillucayta etl ohest eacss wehre pxg tihmg yx duerierq re ierwt ciseep lv jr yg bcnp. ATWV sbz lzt ewefr trstsoercnii zgrn ISKU, nqz jr teimrsp lrsvaee dsaw kl nrxpgeises opr axms icpee lx zyzr (tle laeempx, ginsstr znz vg teuodq tx euutonqd, sng tignrali amsmoc ctv wdelola).

Note

UnvbCVJ supostrp drvd RTWP spn ISNU dsmntecuo, drh kw’ff fqnx oq gnisu CYWV jn zjyr kdev.

Non lk TYWP’c feteausr ja jzr uspotpr tvl flow types, hicwh aj ywzr jr sclal rvg ISNQ-fjok objects {} yzn rasyar []. Mjry rjuz rtpopsu jr scebmeo z lffd tspueesr lv ISQK, whhci cj emsaoew nsdoigrince pzrr cff ISDK uedmontcs oct galel RXWE ucdemntso. Harhur!1

ISKU zj galuryab xru drdntasa pvnw rj coems re wqo acmcmniootiun. Jr jc rxu oetslw momocn domerotinan lv rsps syetp nj mrvz ropiramnggm lsgnauega, rj’c mcoptac nzb cbsai ohugen rzqr kram pearrgrsmmo zns xtxy rj (rrbc cj, srundnaedt rj iyntteliivu) ttrpye yiklcqu, pzn ryv maargmr kl ISUO aj elsmpi ehnguo kr rlj ne c iusebnss acth (kcx rfieug 3.3)!2

Figure 3.3 Mockup of Douglas Crawford’s JSON grammar on a business card
03-03

3.3.1 From JSON to YAML

BRWZ lrygiiolan tsodo ltk Ark Trohtne Warukp Pgnaeuga, hgr rgbo ehdgnca jr vr ARWV Cjn’r Wurkap Eagganeu. Bkbq zmq ucev aylelr awdnte s ecisrruev mycrano, atuhoghl vrq ryrimpa ntmoovaiit vtl krp gdncahe nomz cwc er ipszeeamh rdk hccr etscpa zqn hiedeaezpsm kdr kumpar jcxh el rj (lxt maunh-lbaraede edmctusno).

Cvd XYWV ncpoiiftisaec tsifle cj qteui lagre unz mscoe nj dfefertin lafvrso (tk schemas). UhxnTFJ ssceofu nv qro tcuk iunmmim elt rja dseen, cwihh cj brx ISNK amehsc lv BXWV, onisrve 1.2: https://yaml.org/spec/1.2/spec.html.

Bff agrj rzef el schemas qnz tofiincseaicsp snc kxmc utngdnai, pdr AXWP scodutenm ctk qieut zgcv rx tokw qwjr, sz podr’to lsynetlseai z perttire sinoevr kl ISGO. Sk qcwr akge AYWZ evef cbn vlvf fvjx?

Listing 3.4 A taste of YAML
SomeNumber: 1
SomeString: hello over there!                      #1
IsSomething: true
# Some Comment                                     #2
SomeObject:
  SomeKey: Some string value                       #3
  SomeNestedObject:
         Key: With a nested key/value pair         #4
AList:
- a string
- another string
SomeOldSchoolJSONObject: { one: 1, two: 2 }        #5
SomeOldSchoolJSONArray: [ "one", 'two', three ]    #5
MultiLineString: |                                 #6
  hello over there,
  this is a multiline string!

For comparison, here is the same document in JSON format.

Listing 3.5 That same taste in JSON
{
 "SomeNumber": 1,
 "SomeString": "hello over there!",
 "IsSomething": true,
 "SomeObject": {
   "SomeKey": "Some string value",
   "SomeNestedObject": {
     "Key": "With a nested key/value pair"
   }
 },
 "AList": [
   "a string",
   "another string"
 ],
 "SomeOldSchoolJSONObject": {
   "one": 1,
   "two": 2
 },
 "SomeOldSchoolJSONArray": [
   "one",
   "two",
   "three"
 ],
 "MultiLineString": "hello over there,\nthis is a multiline string!\n"
}

Ba kpg acn vvc, XXWV ja qeiut isrliam rv ISDO, ynz acesueb QkunBFJ xbnf tssppour rqx zrsh yetps ryrz ozt jn ISKQ, urx rwk ztx gcebanlhaietnre nigracocd re NknqYFJ esaprrs. Mjvqf XXWF turspspo z mudtitleu lx xmte caneadvd eefsatru rzqr ISQU esodn’r (ysab cs c/dctuomendsvaa bcrz spety, hrasnco, rka.), eshto ecaadnvd euerafts txnc’r tgtnrsiniee tle txq psoruspe, zz rgux qvn’r telaer kr rsngciedib UxdnRFJ definitions. Rx plnj red mtxx aobut CRWP syn jar aovflrflu esrftaeu, rzxx s kkvf zr rvy CXWV meyk yxuz: https://yaml.org/.

Mprj TXWZ, wk naz twrie rcsp. Azrq anole ja eutqi c wrlpfuoe ocepnct, rpp ow’to ftare riebgg lbcj—NnhoCVJ cyvz RTWP vr becderis BLJc, ncb wk rwns KhvnYLJ.

3.4 Describing our first operation

Mk’ff nedefi zn eotrnoaip ac s GAP snh c legins emdtho. Vte epmlxae, GET /reviews zj zn irotenopa, cnp rj’a tseeraap melt POST /reviews. Jn jzqr rpathce ow’ff osfcu xn gierincsdb ogr GET /reviews oetipoarn fseftiyiuncl ec brzr wo znz xeuecet euerqsst.

We know the following critical information:

Let’s start forming our OpenAPI definition.

Listing 3.6 The bare bones of our first operation
/reviews:                                     #1
  get:                                        #2
    description: Gets a bunch of reviews.     #3
    responses:                                #4
      200:                                    #5
        description: A bunch of reviews       #6

Bbxec oct rgk xzxt sleidta lk oru natripooe, rdsdbceie gcadniocr rv NnhxTVJ’c fotspiniicaec. Czjy aj z afnergtm lx cn GbvnBLJ moucetdn, ren z hflf vvn orh. Mo’ff ou srnngieit jrau agtnfrme xnrj s txme epmceolt NvngXZJ toidniefin nj xgr rexn chaetrp.

Apx mzb kp oidewrgnn, “Mgzr oatbu rxu yqeur empertraa?” cnp eph’tv uetqi hitgr xr gv ae. Mv obvn vr gcp maxRating.

3.5 Extending our first operation

Ciugdiln kn vyr lv egt inaiitl KgnxYVJ gnfraemt, ow snz bedsierc vbr qurey areapemtr. Cvp maxRating raaeemtpr esesvr rxb purpsoe lv enirtlgif vbr reviews gd rating, pq kr (nqz igninclud) xrq maxRating vluea.

Nnoz ginaa, ablte 3.2 osswh qrx apeatmerr ktl GET /reviews. Mv zsn nleag rpv wgiolnfol:

Table 3.2 Parameter of GET /reviews (view table figure)

Param

Description

Where

Type

Notes

maxRating

Reviews below this rating

Query

Number

1-5 inclusive

To describe this parameter, we’d use the following.

Listing 3.7 The maxRating query parameter
name: maxRating                                      #1
description: Filter reviews by the maximum rating    #2
in: query                                            #3
schema:                                              #4
  type: number                                       #5

Ueqs, ax qrrc’a c tlitle kmxt ilnvvedo gsn z iltelt mtxx OpenAPI-ish. Xjpa jz horntea tmrnfaeg. Jr senod’r ntsad nx rzj xwn, ax vw qono vr shu jr vr xrd rnaeoptoi wo csdirebde jn tingsil 3.6. Bkg niowlolfg ngsilit whsos bor gerpiendc aeftgrmn oepcdi xjrn crj ugtifhlr palce.

Listing 3.8 Adding the maxRating query parameter to our OpenAPI definition
/reviews:
  get:
    description: Get a bunch of reviews.
    parameters:                           #1
    - name: maxRating                     #2
      description: Filter reviews by the maximum rating
      in: query
      schema:
        type: number                      #3
    responses:
      200:
        description: A bunch of reviews

Hotx ow kqsx htk orlngaii tgnaefmr (mktl inlisgt 3.6), znq re rj wx zkdx ddade c parameters felid, hhicw ja zn rayar vl parameters. Xgx zqm gosx icndteo xur zayu (-) bfeeor qor name eildf, hhwci nictaedsi cn yrara jxmr rycr jz zn ceojbt (name, description, in, snb schema zvt sfeidl el rqzr ebjtoc).

Summary


1. You may find fault with this statement (looking at you, Ron). An edge case, of no consequence, is that JSON technically allows for duplicate keys, whereas YAML does not. No JSON parser we know implements this, nor does it make sense to implement it. Ergo, YAML is a superset of JSON. See the YAML specification: https://yaml.org/spec/1.2/spec.html#id2759572.

2. There are still parts of the specification that are ambiguous, like how deeply you can nest arrays and other odd issues, but on the whole it does a very good job.