Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Tools or Specs that can help define API workflows #10

frankkilcommins started this conversation in Ideas
Discussion options

We may not want to reinvent the wheel, so let's share some thoughts on specifications or existing mechanisms that warrant some discussion and considerations as part of this SIG.

Examples:

  • Gherkin
  • UML
  • API Design Systems I also see potential to pivot from proposed spec and leverage something similar for describing flows

Also what learnings can we take from the likes of

  • WS-CDL
  • XPDL
  • BPMN
  • WS-BPEL
  • BPEL for REST
  • JOpera
  • RESTalk

etc.

You must be logged in to vote

Replies: 3 comments 1 reply

Comment options

The schemathesis test frameworks already use openAPI links to model dependencies between calls. We talked last time about this possibility.

This tool has already a kind of workflow engine based on this rule based state engine

You must be logged in to vote
1 reply
Comment options

Hi! Schemathesis author here.

FWIW, I got a few thoughts about Open API links, described here. They are mostly about the limitations for data generation I faced before (especially on runtime expressions). I hope, that it might be helpful here :)

Comment options

Rough example of extension to describe workflows within an OpenAPI spec as proposed by @aduminuc during our meeting on Nov 10th. You can refer to this deck for additional context on the example proposal.

In essence, the proposal introduces the concept of Procedures (name not important for now) which define a set of actions over one or more APIs to achieve an objective.

A procedure defines:

  • A set of input parameters, similarly to what an operation does
  • An ordered list of steps, where each step represents a call to an operation or to another procedure.
  • A set of outputs

Each step describes:

  • Which OpenAPI operation or extension procedure to call
  • How to populate the input parameters
  • Defines success conditions
  • What to do on failure events

Workflows Proposal

The following described two procedures (a.k.a workflows), the first for logging in and retrieving user details and the second for purchasing a pet

x-worflow-sig:
 procedures:
 userloginandretrieve:
 summary: log in and retrieve a user 
 procedureID: userLoginAndRetrieve
 description: Log in a user with a given username and password and then retrieve user details.
 parameters:
 - name: username
 description: The user name for login
 required: true
 schema:
 type: string
 - name: password
 description: The password for login in clear text
 required: true
 schema:
 type: string
 steps:
 - stepId: loginStep
 operationId: loginUser
 description: Login user
 parameters:
 username: $parameters.username
 password: $parameters.password
 success:
 - $response.code == 200
 - stepId: getUserStep
 oprationRef: https://petstore3.swagger.io/api/v3/openapi.json#/paths/~1user~1{username}/get
 parameters:
 username: $parameters.username
 success:
 - $response.code == 200
 outputs:
 user: $steps.getUserStep.responses.200
 petpurchase:
 summary: purchase a pet by name
 procedureID: purchasePetByName
 description: A procedure to pick and purchase a pet knowing its name
 parameters:
 - name: petName
 description: Name of pet to purchase
 required: true
 schema:
 type: string
 - name: username
 in: query
 description: The user name for login
 required: true
 schema:
 type: string
 - name: password
 in: query
 description: The password for login in clear text
 required: true
 schema:
 type: string
 steps:
 - stepId: getUserStep
 procedureId: userLoginAndRetrieve
 parameters:
 username: $parameters.username
 password: $parameters.password
 success:
 - $outputs.user.address is not None
 onFailure: exit
 - stepId: getPetStep
 description: retrieve a Pet by Name
 operationID: getPetByName
 parameters:
 petName: $parameters.petName
 success:
 - $response.code == 200
 - $response.200.status == 'available'
 onFailure: exit
 - stepId: purchaseStep
 description: place order
 operationId: placeOrder
 requestBody:
 petId: $steps.getPetStep.responses.200.petID
 address: $steps.getUserStep.outputs.user.address
 success:
 - $response.code == 200
 - $response.200.status == "approved" 
 onFailure: retry
 ouputs:
 order: $steps.purchaseStep.responses.200

Below is the Petstore OpenAPI specification with the additional extension at the end.

openapi: 3.0.2
info:
 title: Swagger Petstore - OpenAPI 3.0
 description: |-
 This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about
 Swagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
 You can now help us improve the API whether it's by making changes to the definition itself or to the code.
 That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
 Some useful links:
 - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
 - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
 termsOfService: http://swagger.io/terms/
 contact:
 email: apiteam@swagger.io
 license:
 name: Apache 2.0
 url: http://www.apache.org/licenses/LICENSE-2.0.html
 version: 1.0.6
externalDocs:
 description: Find out more about Swagger
 url: http://swagger.io
servers:
 - url: /api/v3
tags:
 - name: pet
 description: Everything about your Pets
 externalDocs:
 description: Find out more
 url: http://swagger.io
 - name: store
 description: Operations about user
 - name: user
 description: Access to Petstore orders
 externalDocs:
 description: Find out more about our store
 url: http://swagger.io
paths:
 /pet:
 put:
 tags:
 - pet
 summary: Update an existing pet
 description: Update an existing pet by Id
 operationId: updatePet
 requestBody:
 description: Update an existent pet in the store
 content:
 application/json:
 schema:
 $ref: '#/components/schemas/Pet'
 required: true
 responses:
 '200':
 description: Successful operation
 content:
 application/json:
 schema:
 $ref: '#/components/schemas/Pet'
 links:
 GetPetById:
 operationId: getPetById
 parameters:
 petId : '#response.body#/id'
 description: ID returned by this method can be used to retrieve the Pet
 '400':
 description: Invalid ID supplied
 '404':
 description: Pet not found
 '405':
 description: Validation exception
 security:
 - petstore_auth:
 - write:pets
 - read:pets
 post:
 tags:
 - pet
 summary: Add a new pet to the store
 description: Add a new pet to the store
 operationId: addPet
 requestBody:
 description: Create a new pet in the store
 content:
 application/json:
 schema:
 $ref: '#/components/schemas/Pet'
 required: true
 responses:
 '200':
 description: Successful operation
 content:
 application/xml:
 schema:
 $ref: '#/components/schemas/Pet'
 application/json:
 schema:
 $ref: '#/components/schemas/Pet'
 '405':
 description: Invalid input
 security:
 - petstore_auth:
 - write:pets
 - read:pets
 /pet/findByName/{petName}:
 get:
 tags:
 - pet
 summary: Finds a pet by name
 description: Find a pet by name
 operationId: findPetByName
 parameters:
 - name: petName
 in: path
 description: Name of pet to return
 required: true
 schema:
 type: string
 responses:
 '200':
 description: successful operation
 content:
 application/xml:
 schema:
 type: array
 items:
 $ref: '#/components/schemas/Pet'
 application/json:
 schema:
 type: array
 items:
 $ref: '#/components/schemas/Pet'
 '400':
 description: Invalid status value
 security:
 - petstore_auth:
 - write:pets
 - read:pets
 /pet/{petId}:
 get:
 tags:
 - pet
 summary: Find pet by ID
 description: Returns a single pet
 operationId: getPetById
 parameters:
 - name: petId
 in: path
 description: ID of pet to return
 required: true
 schema:
 type: integer
 format: int64
 responses:
 '200':
 description: successful operation
 content:
 application/xml:
 schema:
 $ref: '#/components/schemas/Pet'
 application/json:
 schema:
 $ref: '#/components/schemas/Pet'
 '400':
 description: Invalid ID supplied
 '404':
 description: Pet not found
 security:
 - api_key: []
 - petstore_auth:
 - write:pets
 - read:pets
 post:
 tags:
 - pet
 summary: Updates a pet in the store with form data
 description: ''
 operationId: updatePetWithForm
 parameters:
 - name: petId
 in: path
 description: ID of pet that needs to be updated
 required: true
 schema:
 type: integer
 format: int64
 - name: name
 in: query
 description: Name of pet that needs to be updated
 schema:
 type: string
 - name: status
 in: query
 description: Status of pet that needs to be updated
 schema:
 type: string
 responses:
 '405':
 description: Invalid input
 security:
 - petstore_auth:
 - write:pets
 - read:pets
 delete:
 tags:
 - pet
 summary: Deletes a pet
 description: ''
 operationId: deletePet
 parameters:
 - name: api_key
 in: header
 description: ''
 required: false
 schema:
 type: string
 - name: petId
 in: path
 description: Pet id to delete
 required: true
 schema:
 type: integer
 format: int64
 responses:
 '400':
 description: Invalid pet value
 security:
 - petstore_auth:
 - write:pets
 - read:pets
 /store/order:
 post:
 tags:
 - store
 summary: Place an order for a pet
 description: Place a new order in the store
 operationId: placeOrder
 parameters:
 - name: petId
 in: query
 description: ID of pet to return
 required: true
 schema:
 type: integer
 format: int64
 requestBody:
 content:
 application/json:
 schema:
 $ref: '#/components/schemas/Order'
 application/xml:
 schema:
 $ref: '#/components/schemas/Order'
 application/x-www-form-urlencoded:
 schema:
 $ref: '#/components/schemas/Order'
 responses:
 '200':
 description: successful operation
 content:
 application/json:
 schema:
 $ref: '#/components/schemas/Order'
 '405':
 description: Invalid input
 /store/order/{orderId}:
 get:
 tags:
 - store
 summary: Find purchase order by ID
 description: For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
 operationId: getOrderById
 parameters:
 - name: orderId
 in: path
 description: ID of order that needs to be fetched
 required: true
 schema:
 type: integer
 format: int64
 responses:
 '200':
 description: successful operation
 content:
 application/xml:
 schema:
 $ref: '#/components/schemas/Order'
 application/json:
 schema:
 $ref: '#/components/schemas/Order'
 '400':
 description: Invalid ID supplied
 '404':
 description: Order not found
 delete:
 tags:
 - store
 summary: Delete purchase order by ID
 description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
 operationId: deleteOrder
 parameters:
 - name: orderId
 in: path
 description: ID of the order that needs to be deleted
 required: true
 schema:
 type: integer
 format: int64
 responses:
 '400':
 description: Invalid ID supplied
 '404':
 description: Order not found
 /user:
 post:
 tags:
 - user
 summary: Create user
 description: This can only be done by the logged in user.
 operationId: createUser
 requestBody:
 description: Created user object
 content:
 application/json:
 schema:
 $ref: '#/components/schemas/User'
 application/xml:
 schema:
 $ref: '#/components/schemas/User'
 application/x-www-form-urlencoded:
 schema:
 $ref: '#/components/schemas/User'
 responses:
 default:
 description: successful operation
 content:
 application/json:
 schema:
 $ref: '#/components/schemas/User'
 application/xml:
 schema:
 $ref: '#/components/schemas/User'
 /user/login:
 get:
 tags:
 - user
 summary: Logs user into the system
 description: ''
 operationId: loginUser
 parameters:
 - name: username
 in: query
 description: The user name for login
 required: false
 schema:
 type: string
 - name: password
 in: query
 description: The password for login in clear text
 required: false
 schema:
 type: string
 responses:
 '200':
 description: successful operation
 headers:
 X-Rate-Limit:
 description: calls per hour allowed by the user
 schema:
 type: integer
 format: int32
 X-Expires-After:
 description: date in UTC when token expires
 schema:
 type: string
 format: date-time
 content:
 application/xml:
 schema:
 type: string
 application/json:
 schema:
 type: string
 '400':
 description: Invalid username/password supplied
 /user/logout:
 get:
 tags:
 - user
 summary: Logs out current logged in user session
 description: ''
 operationId: logoutUser
 parameters: []
 responses:
 default:
 description: successful operation
 /user/{username}:
 get:
 tags:
 - user
 summary: Get user by user name
 description: ''
 operationId: getUserByName
 parameters:
 - name: username
 in: path
 description: 'The name that needs to be fetched. Use user1 for testing. '
 required: true
 schema:
 type: string
 responses:
 '200':
 description: successful operation
 content:
 application/xml:
 schema:
 $ref: '#/components/schemas/User'
 application/json:
 schema:
 $ref: '#/components/schemas/User'
 '400':
 description: Invalid username supplied
 '404':
 description: User not found
 put:
 tags:
 - user
 summary: Update user
 description: This can only be done by the logged in user.
 operationId: updateUser
 parameters:
 - name: username
 in: path
 description: name that need to be deleted
 required: true
 schema:
 type: string
 requestBody:
 description: Update an existent user in the store
 content:
 application/json:
 schema:
 $ref: '#/components/schemas/User'
 application/xml:
 schema:
 $ref: '#/components/schemas/User'
 application/x-www-form-urlencoded:
 schema:
 $ref: '#/components/schemas/User'
 responses:
 default:
 description: successful operation
 delete:
 tags:
 - user
 summary: Delete user
 description: This can only be done by the logged in user.
 operationId: deleteUser
 parameters:
 - name: username
 in: path
 description: The name that needs to be deleted
 required: true
 schema:
 type: string
 responses:
 '400':
 description: Invalid username supplied
 '404':
 description: User not found
components:
 schemas:
 OrderCreate:
 type: object
 properties:
 petId:
 type: integer
 format: int64
 example: 198772
 address:
 $ref: '#/components/schemas/Address' 
 xml:
 name: order
 Order:
 type: object
 properties:
 id:
 type: integer
 format: int64
 example: 10
 petId:
 type: integer
 format: int64
 example: 198772
 address:
 $ref: '#/components/schemas/Address' 
 shipDate:
 type: string
 format: date-time
 status:
 type: string
 description: Order Status
 example: approved
 enum:
 - placed
 - approved
 - delivered
 complete:
 type: boolean
 xml:
 name: order
 Address:
 type: object
 properties:
 street:
 type: string
 example: 437 Lytton
 city:
 type: string
 example: Palo Alto
 state:
 type: string
 example: CA
 zip:
 type: string
 example: '94301'
 xml:
 name: address
 Category:
 type: object
 properties:
 id:
 type: integer
 format: int64
 example: 1
 name:
 type: string
 example: Dogs
 xml:
 name: category
 User:
 type: object
 properties:
 id:
 type: integer
 format: int64
 example: 10
 username:
 type: string
 example: theUser
 firstName:
 type: string
 example: John
 lastName:
 type: string
 example: James
 email:
 type: string
 example: john@email.com
 password:
 type: string
 example: '12345'
 phone:
 type: string
 example: '12345'
 userStatus:
 type: integer
 description: User Status
 format: int32
 example: 1
 address:
 $ref: '#/components/schemas/Address'
 xml:
 name: user
 Tag:
 type: object
 properties:
 id:
 type: integer
 format: int64
 name:
 type: string
 xml:
 name: tag
 Pet:
 required:
 - name
 - photoUrls
 type: object
 properties:
 id:
 type: integer
 format: int64
 example: 10
 name:
 type: string
 example: doggie
 category:
 $ref: '#/components/schemas/Category'
 photoUrls:
 type: array
 xml:
 wrapped: true
 items:
 type: string
 xml:
 name: photoUrl
 tags:
 type: array
 xml:
 wrapped: true
 items:
 $ref: '#/components/schemas/Tag'
 status:
 type: string
 description: pet status in the store
 enum:
 - available
 - pending
 - sold
 xml:
 name: pet
 securitySchemes:
 petstore_auth:
 type: oauth2
 flows:
 implicit:
 authorizationUrl: https://petstore3.swagger.io/oauth/authorize
 scopes:
 write:pets: modify pets in your account
 read:pets: read your pets
 api_key:
 type: apiKey
 name: api_key
 in: header
x-worflow-sig:
 procedures:
 userloginandretrieve:
 summary: log in and retrieve a user 
 procedureID: userLoginAndRetrieve
 description: Log in a user with a given username and password and then retrieve user details.
 parameters:
 - name: username
 description: The user name for login
 required: true
 schema:
 type: string
 - name: password
 description: The password for login in clear text
 required: true
 schema:
 type: string
 steps:
 - stepId: loginStep
 operationId: loginUser
 description: Login user
 parameters:
 username: $parameters.username
 password: $parameters.password
 success:
 - $response.code == 200
 - stepId: getUserStep
 oprationRef: https://petstore3.swagger.io/api/v3/openapi.json#/paths/~1user~1{username}/get
 parameters:
 username: $parameters.username
 success:
 - $response.code == 200
 outputs:
 user: $steps.getUserStep.responses.200
 petpurchase:
 summary: purchase a pet by name
 procedureID: purchasePetByName
 description: A procedure to pick and purchase a pet knowing its name
 parameters:
 - name: petName
 description: Name of pet to purchase
 required: true
 schema:
 type: string
 - name: username
 in: query
 description: The user name for login
 required: true
 schema:
 type: string
 - name: password
 in: query
 description: The password for login in clear text
 required: true
 schema:
 type: string
 steps:
 - stepId: getUserStep
 procedureId: userLoginAndRetrieve
 parameters:
 username: $parameters.username
 password: $parameters.password
 success:
 - $outputs.user.address is not None
 onFailure: exit
 - stepId: getPetStep
 description: retrieve a Pet by Name
 operationID: getPetByName
 parameters:
 petName: $parameters.petName
 success:
 - $response.code == 200
 - $response.200.status == 'available'
 onFailure: exit
 - stepId: purchaseStep
 description: place order
 operationId: placeOrder
 requestBody:
 petId: $steps.getPetStep.responses.200.petID
 address: $steps.getUserStep.outputs.user.address
 success:
 - $response.code == 200
 - $response.200.status == "approved" 
 onFailure: retry
 ouputs:
 order: $steps.purchaseStep.responses.200
You must be logged in to vote
0 replies
Comment options

Here is an attempt at representing a sequence of calls that make up an OpenID Connect flow, specifically an Authorization code flow with a Pushed Authorization Request. I have tried to make it a accurate as possible but there may be a few errors here an there. This is not to be used as the basis for OIDC documentation! Also there are probably things that are in the existing OAI spec that could help with this example but I am not yet expert in OAI.

I have taken a lot of inspiration from the contribution above but a number of aspects either didn't quite work or just didn't feel right in the context of the example presented. Some of these issues are addressed with changes and others I have not come up with a reasonable idea for yet.

Also as per comment above names of elements are not terribly important for now.

Things adjusted between the petstore example and this:

  • I added a new element called participants - this is to capture the list of source and destination and allow for additional attributes to be documented - I have not come up with additional participant attributes yet
  • I renamed "procedures.parameters" to "procedure.variables" - it appears to me that this will reduce confusion about parameters of a single call with variables needed for a procedure
  • The variables is also not a complete list of all parameters used in all the calls, just what is needed as input to a procedure
  • I am not feeling comfortable with structured objects being defined inside "procedure.variables" but I have done a couple there and one inside "step.xxx.parameters" to compare and contrast
  • There may well be multiple requestBody elements needed for a procedure so I have given the two needed in this example specific names (this may not be needed if we end up defining them inside each step they are needed within)
  • source and destination within each step matching members of the list of participants. In this example there are two sources
  • In the step parameters I have added some schema content and a key called value where static values are used for a given procedure step

Things I am concerned about but have not addressed

  • The Authorization endpoint call was not represented within OAI as it is from a user agent and a successful response is a 302 redirect
  • The client assertion paramer gives a particular challenge because there are two uses of it in this procedure and they have different content, It is in the form of a JWS and it must contain a unique jti value and an accurate iat value (issued at) and then it must be signed.
  • It feels likely that further functions will be needed. In this example there appears to be a need for random, time and sign
  • In the list of steps it might be useful to add an index number - not sure

AuthenticationAPI-v3.0.0-procedure-PAR&OIDCalpha2.yaml.txt

apparently not allowed to upload .yaml files here

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

AltStyle によって変換されたページ (->オリジナル) /