Skip to content

Design and document a Builder pattern for API payloads #93

@devraj

Description

@devraj

Is your feature request related to a problem? Please describe.
A real (incorrect) example of creating a card is something like this (not using the library, just httpx and ignore the hard coded URLs

    # Make a call to issue a card
    add_payload = {
        "cards": {
            "add": [{
                "type": {
                    "href": "https://commandcentre-api-au.security.gallagher.cloud/api/card_types/301"
                },
                "invitation": {
                    "singleFactorOnly": True
                }
            }]
        }
    }

    # Use httpx to call cardholder.edit.href with this payload
    async with httpx.AsyncClient() as client:
        # add the header "Authorization: GGL-API-KEY"
        client.headers["Authorization"] = "GGL-API-KEY " + os.environ.get("GACC_API_KEY")
        response = await client.patch(str(cardholder.edit.href).replace("/edit", ""), json=add_payload)

The same payload can have a "remove" key with a card href which would make the command centre add a card and remove another in the same call.

To express this properly we should consider a builder pattern for the API payloads.

These make the Python code extremely expressive.

I have experienced similar things in Stripe's Terminal SDK where you want to conditionally add a payload.

Describe the solution you'd like
Consider providing a base utility class that payload builders can inherit from and it ultimately is able to produce the JSON that is sent to the server.

It could look something like:

    add_card_href = CardTypeRef(href="https://api.example.com/cards/123")
    remove_card_href = HrefMixin(href="https://api.example.com/cards/456")

    card_update_builder = CardholderUpdateBuilder()
        .add_card(add_card_href)
        .remove_card(remove_card_href)
        .build()

This would allow conditional chaining of requests.

Some things to consider here are:

  • Should we allow the user to pass hrefs or ids of particular objects (this is probably something I need to consider broadly around the project
  • What does inheritance look like for payload providers

Describe alternatives you've considered
NA

Additional context

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions