Skip to content

Use Pydantic discriminator so we can easily parse webhooks #21

@emhagman

Description

@emhagman

Hi!

We use the Vapi SDK for both the client but also for type checking in our webhooks we received. Currently, we have to do some reflection with Pydantic to more easily/programatically parse the events.

However, Pydantic supports discriminators https://docs.pydantic.dev/latest/concepts/fields/#discriminator where a field can determine the model type. It would be really nice to be able to do something like:

@router.post("/vapi/events")
async def webhook_vapi_events(request: Request):
    # make sure the data coming in is from vapi
    if not authorize_vapi_webhook_request(request):
        logger.warning("Invalid secret supplied via webhook")
        return JSONResponse(status_code=401, content={"status": "error", "message": "Invalid secret"})

    # continue processing
    json_data = await request.json()

    # parse our event
    event_type = VapiEvent.model_validate(json_data)

    # pydantic automatically maps/casts to the model
    # event_type: ServerMessageStatusUpdate in the case of `status-update`
    ...

Currently, we have to have a mapping from type to each model like so:

    message = json_data.get("message")
    if not message:
        logger.warning("No message found in request")
        return {"status": "missing-message"}

    raw_type = message.get("type")
    if not raw_type:
        logger.warning("No message type found in request")
        return {"status": "missing-message-type"}

    # we have to manually parse models
    event = mapping[raw_type]
    

Where mapping is a generated via reflection from ServerMessageStatusUpdate etc based on the type field which used to be a default string but currently uses literals.

Are there any future plans to support discriminators in the future to more easily parse these? I believe you use fern to generate your SDK and they do support this: https://buildwithfern.com/learn/api-definitions/ferndef/types#discriminated-unions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions