Redoc: [openapi-3] callbacks support

Created on 21 Jan 2018  Â·  16Comments  Â·  Source: Redocly/redoc

OpenAPI 3.0 has callbacks support: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#operation-object

It would be great to support them in ReDoc but I don't have any idea of how to visualize them yet.
Let's share ideas/discuss it here.

help wanted

Most helpful comment

Hi - inquiring if this is being considered. IMO it would be a highly valuable feature.

All 16 comments

As the callback object wraps a pathItem object, in widdershins and openapi-gui I've rendered callbacks by repeating the pathItem template/component, but within a visually distinct containing <div> and in a separate tab, respectively. This handles the (admittedly unlikely) case of a callback object having its own callbacks.

Is there any update on this issue?

Hi - inquiring if this is being considered. IMO it would be a highly valuable feature.

I would also be interested in such a feature.

Example OpenAPI spec: callback.yaml (based on the Swagger callbacks documentation page)

Rendering on the ReDoc Interactive Demo (not working yet).


As comparison how other tools are doing this:

OpenAPI-GUI:

mentioned by @MikeRalphson in https://github.com/Redocly/redoc/issues/411#issuecomment-360113497

OpenAPI-GUI displaying a simple callback spec
(more an editor than a display, but the interesting point in the "callbacks" tab)

Swagger-UI:

Swagger-UI displaying a simple callback spec


In my opinion, the problem with representing the callbacks under an operation makes sense from an Editing point of view but is not really what the used need:

But often when you look at a reference documentation you are more interested by "what can call me?", meaning by a list of all callback-operations that can be send by the server and that you need to handle.

An implementation could be:

  • Collect all operations from all callbacks defined in a spec.
  • Display them under a top level item (same rendering as the "Authentication" or as a "tag" in the ToC). Maybe with a text-color or an icon (next to the HTTP-Method) to indicate that this is a callback.
  • On the page that describes one callback-operation, add a note about the fact that it is a callback-operation and a deep link to the operation used to register. The path is also dependent from the registration.
  • On the normal operation that have callbacks defined, add a deep-link to the callback.

Because our callbacks operation are always the same (we send a given Schema as Request-Body of a POST method), I have implemented a small PoC of what I have described above:

There is a main section "Callbacks events" and each callback is documented as separated entry in the tree.

Screenshot 2019-08-27 at 11 03 44

See spec: todoAppWithCallbacks.yaml (ReDoc live demo)


This is using the <SchemaDefinition schemaRef="..." /> markdown macro introduced by @nanov and discussed in #134.

I would prefer to have an <OperationDefintion operationId="…"> macro, this would be more generic and this way I would not have to write "_Following request-body is send as POST request on the URL used to register the callback_"

I did not investigate how to create links between the operation and the callback description.

@jmini I don't know if the issue is your api definition, or with the implementation in Redoc. Here is what I noticed.

image

image

I think my confusion is mainly due to the api definition mismatching names event, event name and eventType. I suppose this could be resolved by tightening up that definition. Overall, this seems kind of cool.

I understand the desire to not have this:

Following request-body is send as POST request on the URL used to register the callback

However, I can't see where in the definition it would show that the callback is made via a POST (as opposed to a GET for example). In other words, I'm wondering how all of that could be grabbed automatically from your definition, and eliminate entirely the need for any special inline tags.

First of all, thank you for your feedback and sorry for the delay.


I agree the OpenAPI spec that I have proposed to test this might not be ideal (design is not perfect), but is representative of the spec we are currently using in the project (some stuff can not be changed for backward compatibility).

I totally get your point about the events attribute in CallbackRegistration schema. It could be better.

Nevertheless this is not enforced by the OpenAPI spec, it is possible to have a registration operation that do not let you filter the kind of event you would like to receive (probably you do just get all events).


The prototype I have proposed in my previous comment is something that can be done with the current ReDoc version by adding the callback tag to create the “Callbacks events” in the tree:

https://github.com/jmini/openapi-experiments/blob/4eb908cdf0d3d5382b9e8da2a761669736f25b18/OpenAPI-specs/todoAppWithCallbacks.yaml#L18-L31


The Callbacks are defined under the path /callback for the POST operation
https://github.com/jmini/openapi-experiments/blob/master/OpenAPI-specs/todoAppWithCallbacks.yaml#L293-L319

If would be great if based of this input, ReDoc would automatically:

1a) Create the “Callbacks events” in the tree

In this section you see all the callback events that can be received, with a label indicating the HTTP method and maybe an other marked (I have used ↙ in my screenshot) to indicate that this node is not an endpoint defined by the server but an endpoint that the client needs to implement to receive callbacks

Screenshot Callbacks events

In my example there are only “POST” request callback, but you could also imagine that the sever is sending other calls to the client that is receiving the callback request.

Screenshot Callbacks with multiple HTTP request

1b) For each Callback event, instead of my quick hack _"Following request-body is send as POST…"_, a complete representation of the operation should be displayed:

Screenshot Callback description

  • HTTP Method is important.
  • Mentioning that the endpoint URL is configurable (I have used /{your-endpoint} in my screenshot)
  • Responses: they are also important because there are setup where this is used to unsubscribe for the callback (receiving server can return specific code in response to the callback message to indicate that it is no longer interested in callbacks).

2a) In the Operation where the callbacks are defined:

There should be a section that indicates that callbacks are defined for this operation:

Screenshot operation

I am not sure about the position, it should probably be after "Responses".
The links should allow to jump to the corresponding event in the "Callbacks events" section.

2b) The other way around: in one page displaying one callback, you could also imagine a link to the registration operation (the operation that defines the callback in the OpenAPI Spec).


I hope this makes my vision for Callbacks in ReDoc more clear. If not feel free to ask.

Hi everyone, are there any news regarding the callback support of redoc?

It appears to be supported in my currently used 2.0.0-rc.27

Fixed by #1224

Thanks @forivall

Yes. We added support for this since rc.27: https://github.com/Redocly/redoc/pull/1224

Are callbacks supported for redoc-cli?

I followed the guide to add callbacks at https://swagger.io/docs/specification/callbacks/.

Can't seem to get it to build properly.

Builds just fine on swagger.

The version of redoc-cli is 0.9.7.

npx redoc-cli --version
0.9.7

No Callback tab on redoc

Screenshot from 2020-06-29 22-34-13

Works on Swagger

Screenshot from 2020-06-29 22-34-06

Edited: Added images.

@jaspersorrio what version of redoc-cli are you using? any other details you can provide?

Can't seem to get it to build properly.

Could you explain what this means? Can you share your definition? or minimal reproducible sample?

Hi @RomanHotsiy,

You may use this snippet to reproduce the "bug".

openapi: 3.0.1
info:
  title: example API Documentation BETA (latest)
  description: "This page contains the documentation on how to use example through API calls.\n
    \n
    <h3>Previous API versions</h3>
    <a href='/api/v1'>API V1.0</a>"
  termsOfService: https://example.sg/terms-of-use
  contact:
    email: [email protected]
  version: "1.1"
servers:
- url: https://api.example.sg
- url: https://api.example.dev

tags:
  - name: Chat
    description: Chat with EXAMPLE dedicated customer service support without the need to leave your app by starting and replying chat sessions with example Chat Api.

  - name: Chat_Model
    x-displayName: The Chat Model
    description: |
      <SchemaDefinition schemaRef="#/components/schemas/Chat" />

x-tagGroups:
  - name: General
    tags:
      - Chat
  - name: Models
    tags:
      - Chat_Model

paths:
  /api/v1.1/chat:
    post:
      tags:
      - Chat
      summary: Start a Chat

      callbacks:    
        ReplyChatEvent:     
          $ref: "#/components/callbacks/ReplyChatEvent"
      requestBody:
        $ref: "#/components/requestBodies/ChatBody"

      responses:
        200:
          description: Success
          content: 
            application/json:
              schema:
                required:
                  - success
                  - chatId
                type: object
                properties:
                  success: 
                    type: boolean
                    example: true
                  chatId:
                    $ref: '#/components/schemas/Chat/properties/chatId'

  /api/v1.1/chat/{id}:

    post:
      tags:
      - Chat
      summary: Reply a Chat
      parameters:
        - in: path
          name: id
          required: true
          description: The chatId you want to reply to.
          schema:
            $ref: '#/components/schemas/Chat/properties/chatId'

      requestBody:
        $ref: "#/components/requestBodies/ChatBody"

      responses:
        200:
          description: Success
          content: 
            application/json:
              schema:
                required:
                  - success
                  - chatId
                type: object
                properties:
                  success: 
                    type: boolean
                    example: true
                  chatId:
                    $ref: '#/components/schemas/Chat/properties/chatId'
components:

  # 
  # COMPONENTS > CALLBACKS
  # 

  callbacks:    
    ReplyChatEvent: 
      '{$request.body#/responseUrl}':   
        post:   
          requestBody:   # Contents of the callback message 
            required: true  
            content:    
              application/json: 
                schema: 
                  $ref: "#/components/schemas/Chat" 
          responses:   # Expected responses to the callback message 
            '200':  
              description: REQUIRED - Your server returns this code if it accepts the callback

  #
  # COMPONENTS > REQUEST BODIES
  #
  requestBodies:
    ChatBody: 
      required: true
      content: 
        application/json: 
          schema: 
            type: object
            required: 
              - subject
              - message
              - responseUrl
            properties:
              subject:
                type: string
                example: Loctite 243 Threadlocker 50ml
                description: The subject of the thread
              message:
                type: string
                example: Can we get a cheaper price?
                description: The message to be sent
              responseUrl:
                description: The webhook that example should make the POST request when the replying party replies.
                type: string
                example: https://webhook.site/e1d8a451-9a4f-4d2b-8080-dfdb8ffa511c

  #
  # COMPONENTS > SCHEMAS
  #
  schemas:
    Chat:
      type: object
      properties: 
        chatId: 
          description: The chat's _id. Required when replying to a Chat.
          type: string
          example: 8e59d4cc-34ef-4ad4-a922-01bc2d347d24
        message: 
          description: The chat's message / content
          type: string
          example: This order will arrive on monday
        subject: 
          description: The subject of the chat
          type: string
          example: Order Id INV-2002-200

  securitySchemes:
    apiKey:
      type: apiKey
      name: X-example-API-KEY
      in: header

security:
  - apiKey: []

I just run openapi-cli and I can see callbacks.

image

The latest version of redoc-cli is:

npx redoc-cli --version
0.9.8

You must have cached the older one. Try adding version explicitly npx [email protected]

@RomanHotsiy, you just saved me so much time, I am so grateful for your help.

Thank You so much!!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jaroslawr picture jaroslawr  Â·  3Comments

ahshum picture ahshum  Â·  3Comments

skllcrn picture skllcrn  Â·  3Comments

lafrech picture lafrech  Â·  3Comments

bmarwell picture bmarwell  Â·  3Comments