{
    "openapi": "3.1.0",
    "info": {
        "title": "Masar API",
        "version": "1.0.0",
        "description": "Masar REST API for secure, tenant-isolated business messaging. The credential identifies the account: no endpoint takes an account id, and a resource belonging to another account answers 404."
    },
    "servers": [
        {
            "url": "https:\/\/router.atyaf.co\/api"
        }
    ],
    "security": [
        {
            "bearerAuth": []
        }
    ],
    "paths": {
        "\/v1\/balance": {
            "get": {
                "operationId": "v1.balance",
                "tags": [
                    "Balance"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "balance_microusd": {
                                                    "type": "integer"
                                                },
                                                "balance": {
                                                    "type": "string"
                                                },
                                                "currency": {
                                                    "type": "string"
                                                },
                                                "plan": {
                                                    "type": "string"
                                                }
                                            },
                                            "required": [
                                                "balance_microusd",
                                                "balance",
                                                "currency",
                                                "plan"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/campaigns": {
            "get": {
                "operationId": "v1.campaigns.index",
                "tags": [
                    "Campaign"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "page": {
                                                    "type": "integer"
                                                },
                                                "per_page": {
                                                    "type": "integer"
                                                },
                                                "total": {
                                                    "type": "integer"
                                                },
                                                "last_page": {
                                                    "type": "integer"
                                                }
                                            },
                                            "required": [
                                                "page",
                                                "per_page",
                                                "total",
                                                "last_page"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "v1.campaigns.store",
                "description": "Nothing is frozen, nothing is priced and nothing is reserved, so an\nabandoned draft costs its owner nothing. It carries no launch claim\neither \u2014 the unique index that stops a browser resubmission creating a\nsecond campaign is keyed on a hash of a FORM, and a caller with an id in\nhand does not need it. Their retry protection is the idempotency key.",
                "summary": "Create a draft",
                "tags": [
                    "Campaign"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A unique string for THIS call. The same key with the same body replays the first answer and does nothing twice; a different body under the same key is refused. A UUID per call is the usual choice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 120
                                    },
                                    "channel_id": {
                                        "type": "integer"
                                    },
                                    "template_id": {
                                        "type": "integer"
                                    },
                                    "contact_list_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "description": "Nullable: \"everyone in my address book\" is a legitimate audience,\nand forcing a list to exist first is a step that teaches an\nintegrator nothing."
                                    },
                                    "variables": {
                                        "type": [
                                            "array",
                                            "null"
                                        ],
                                        "items": {
                                            "type": [
                                                "string",
                                                "null"
                                            ]
                                        }
                                    }
                                },
                                "required": [
                                    "name",
                                    "channel_id",
                                    "template_id"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/campaigns\/{campaign}": {
            "get": {
                "operationId": "v1.campaigns.show",
                "tags": [
                    "Campaign"
                ],
                "parameters": [
                    {
                        "name": "campaign",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "string"
                                                },
                                                "channel_id": {
                                                    "type": "integer"
                                                },
                                                "template_id": {
                                                    "type": "integer"
                                                },
                                                "contact_list_id": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "recipients_count": {
                                                    "type": "integer"
                                                },
                                                "sent_count": {
                                                    "type": "integer"
                                                },
                                                "delivered_count": {
                                                    "type": "integer"
                                                },
                                                "read_count": {
                                                    "type": "integer"
                                                },
                                                "failed_count": {
                                                    "type": "integer"
                                                },
                                                "estimated_cost_microusd": {
                                                    "type": "integer",
                                                    "description": "Three money columns rather than one, because they answer three\ndifferent questions: what we quoted, what we are holding, and\nwhat has actually been spent. Collapsing them hides the drift\nbetween an estimate and an invoice."
                                                },
                                                "reserved_microusd": {
                                                    "type": "integer"
                                                },
                                                "spent_microusd": {
                                                    "type": "integer"
                                                },
                                                "spent": {
                                                    "type": "string"
                                                },
                                                "scheduled_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "started_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "finished_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "name",
                                                "status",
                                                "channel_id",
                                                "template_id",
                                                "contact_list_id",
                                                "recipients_count",
                                                "sent_count",
                                                "delivered_count",
                                                "read_count",
                                                "failed_count",
                                                "estimated_cost_microusd",
                                                "reserved_microusd",
                                                "spent_microusd",
                                                "spent",
                                                "scheduled_at",
                                                "started_at",
                                                "finished_at",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/campaigns\/{campaign}\/report": {
            "get": {
                "operationId": "v1.campaigns.report",
                "description": "A separate call from `show` because it is a different cost. `show` reads\none row; this runs three aggregates over the frozen audience and over\n`messages`, and an integration polling a running campaign every ten\nseconds should be able to choose which of the two it is paying for.",
                "summary": "The recipient and delivery funnel, and why anything failed",
                "tags": [
                    "Campaign"
                ],
                "parameters": [
                    {
                        "name": "campaign",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "campaign": {
                                                    "type": "object",
                                                    "additionalProperties": {}
                                                },
                                                "recipients": {
                                                    "type": "object",
                                                    "properties": {
                                                        "total": {
                                                            "anyOf": [
                                                                {
                                                                    "type": "integer"
                                                                },
                                                                {
                                                                    "type": "number"
                                                                }
                                                            ]
                                                        },
                                                        "pending": {
                                                            "type": "string"
                                                        },
                                                        "sent": {
                                                            "type": "string"
                                                        },
                                                        "unknown": {
                                                            "type": "integer"
                                                        },
                                                        "delivered": {
                                                            "type": "string"
                                                        },
                                                        "read": {
                                                            "type": "integer"
                                                        },
                                                        "failed": {
                                                            "type": "integer"
                                                        },
                                                        "skipped": {
                                                            "type": "integer"
                                                        }
                                                    },
                                                    "required": [
                                                        "total",
                                                        "pending",
                                                        "sent",
                                                        "unknown",
                                                        "delivered",
                                                        "read",
                                                        "failed",
                                                        "skipped"
                                                    ]
                                                },
                                                "progress_percent": {
                                                    "type": "integer"
                                                },
                                                "delivery_rate": {
                                                    "type": "number",
                                                    "description": "Rates as ratios rather than percentages, and rounded to four\nplaces rather than left as a repeating float: a caller that\nmultiplies by 100 gets a percentage, and a caller that compares\ntwo reports gets numbers that are equal when the underlying\ncounts are."
                                                },
                                                "read_rate": {
                                                    "type": "number"
                                                },
                                                "failure_rate": {
                                                    "type": "number"
                                                },
                                                "reserved_microusd": {
                                                    "type": "integer"
                                                },
                                                "spent_microusd": {
                                                    "type": "integer"
                                                },
                                                "unspent_microusd": {
                                                    "type": "integer"
                                                },
                                                "failure_causes": {
                                                    "type": "array",
                                                    "description": "Grouped by Meta's own error code. \"412 failed\" is a number;\n\"380 of them: not a WhatsApp number\" is an instruction.",
                                                    "items": {
                                                        "anyOf": [
                                                            {
                                                                "type": "object",
                                                                "properties": {
                                                                    "code": {
                                                                        "type": "string"
                                                                    },
                                                                    "count": {
                                                                        "type": "integer"
                                                                    },
                                                                    "example": {
                                                                        "type": [
                                                                            "string",
                                                                            "null"
                                                                        ]
                                                                    }
                                                                },
                                                                "required": [
                                                                    "code",
                                                                    "count",
                                                                    "example"
                                                                ]
                                                            },
                                                            {
                                                                "type": "object",
                                                                "properties": {
                                                                    "code": {
                                                                        "type": "string",
                                                                        "const": "other"
                                                                    },
                                                                    "count": {
                                                                        "type": "integer"
                                                                    },
                                                                    "example": {
                                                                        "type": "null"
                                                                    }
                                                                },
                                                                "required": [
                                                                    "code",
                                                                    "count",
                                                                    "example"
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                },
                                                "skip_reasons": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "reason": {
                                                                "type": "string"
                                                            },
                                                            "count": {
                                                                "type": "integer"
                                                            }
                                                        },
                                                        "required": [
                                                            "reason",
                                                            "count"
                                                        ]
                                                    }
                                                }
                                            },
                                            "required": [
                                                "campaign",
                                                "recipients",
                                                "progress_percent",
                                                "delivery_rate",
                                                "read_rate",
                                                "failure_rate",
                                                "reserved_microusd",
                                                "spent_microusd",
                                                "unspent_microusd",
                                                "failure_causes",
                                                "skip_reasons"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/campaigns\/{campaign}\/start": {
            "post": {
                "operationId": "v1.campaigns.start",
                "description": "`max_cost_microusd` IS REQUIRED, and that is the decision this endpoint\nturns on. An API that starts a bulk send with no stated ceiling is an API\nwhere a list that grew overnight empties a wallet and the first anyone\nknows is the statement. The ceiling costs a caller one integer and buys\nthem a refusal, with the real number in it, instead of a debit.",
                "summary": "Freeze the audience, reserve the quote, and send \u2014 or book it",
                "tags": [
                    "Campaign"
                ],
                "parameters": [
                    {
                        "name": "campaign",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A unique string for THIS call. The same key with the same body replays the first answer and does nothing twice; a different body under the same key is refused. A UUID per call is the usual choice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "scheduled_at": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "date-time"
                                    },
                                    "max_cost_microusd": {
                                        "type": "integer",
                                        "description": "Non-negative rather than positive: a campaign whose every\nrecipient prices to zero \u2014 service-window replies are free at\nMeta and free here \u2014 is a legitimate send with a ceiling of nil.",
                                        "minimum": 0
                                    },
                                    "confirm": {
                                        "type": "boolean"
                                    }
                                },
                                "required": [
                                    "max_cost_microusd",
                                    "confirm"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/campaigns\/{campaign}\/pause": {
            "post": {
                "operationId": "v1.campaigns.pause",
                "description": "No `confirm`: pausing spends nothing and undoes nothing. A caller who\npauses by accident presses resume.",
                "summary": "Stop sending. The reservation stays, because a pause is resumable",
                "tags": [
                    "Campaign"
                ],
                "parameters": [
                    {
                        "name": "campaign",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A unique string for THIS call. The same key with the same body replays the first answer and does nothing twice; a different body under the same key is refused. A UUID per call is the usual choice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/campaigns\/{campaign}\/resume": {
            "post": {
                "operationId": "v1.campaigns.resume",
                "description": "The answer is READ OFF THE CAMPAIGN rather than assumed from the verb,\nbecause resume has three outcomes: a campaign that was sending returns to\n`running`, a booking that has not reached its moment returns to\n`scheduled`, and a booking whose moment passed while it was paused is not\nresumed at all. The last one is the one a caller cannot see for\nthemselves \u2014 the row simply stays as it was \u2014 so the body carries the\nstatus and `paused_reason`, which is where the runner writes why.\n\nNO `confirm`, AND THAT IS NOT THE SAME STATEMENT AS \u00abTHIS IS CHEAP\u00bb. A\nresume restarts the frozen remainder \u2014 the same bulk send `start`\nqueued \u2014 so it shares the send rate bucket and is closed to a test\ncredential exactly as `start` is. What it does not need is a second\nceremony: a caller who resumes by accident presses Pause, and the money\nwas authorised once already, at the launch that reserved it.",
                "summary": "Start sending again \u2014 or put the booking back on the calendar",
                "tags": [
                    "Campaign"
                ],
                "parameters": [
                    {
                        "name": "campaign",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A unique string for THIS call. The same key with the same body replays the first answer and does nothing twice; a different body under the same key is refused. A UUID per call is the usual choice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/campaigns\/{campaign}\/cancel": {
            "post": {
                "operationId": "v1.campaigns.cancel",
                "description": "`confirm: true` is required. This is the one campaign verb that cannot be\nundone: the audience is settled, the unspent reservation is credited back\nin a single movement, and there is no way back to `running`.\n\nIt is also closed to a test credential, by\nApp\\Http\\Middleware\\AuthenticateApiCredential::LIVE_ONLY rather than by\nthe send bucket \u2014 it moves money without sending, and rationing the brake\nat the accelerator's rate would take cancel away at the one moment it is\nworth having. A key that may not start a campaign must not be able to end\nsomebody's live one either.",
                "summary": "Stop for good, and hand back everything that was not sent",
                "tags": [
                    "Campaign"
                ],
                "parameters": [
                    {
                        "name": "campaign",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A unique string for THIS call. The same key with the same body replays the first answer and does nothing twice; a different body under the same key is refused. A UUID per call is the usual choice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be true. This call spends money or cannot be undone."
                                    }
                                },
                                "required": [
                                    "confirm"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/channels": {
            "get": {
                "operationId": "v1.channels.index",
                "tags": [
                    "Channel"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "page": {
                                                    "type": "integer"
                                                },
                                                "per_page": {
                                                    "type": "integer"
                                                },
                                                "total": {
                                                    "type": "integer"
                                                },
                                                "last_page": {
                                                    "type": "integer"
                                                }
                                            },
                                            "required": [
                                                "page",
                                                "per_page",
                                                "total",
                                                "last_page"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/channels\/{channel}": {
            "get": {
                "operationId": "v1.channels.show",
                "tags": [
                    "Channel"
                ],
                "parameters": [
                    {
                        "name": "channel",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "type": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "string"
                                                },
                                                "provider_channel_id": {
                                                    "type": "string",
                                                    "description": "Meta's phone number id. Safe to expose \u2014 it is the id the\ncustomer sees in their own Business Manager, and it is what they\nwill quote when something is wrong with the number."
                                                },
                                                "address": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "verified_name": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "quality_rating": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "ONE OF THE THREE BANDS, OR NULL \u2014 never whatever string happens to\nbe in the column. This is the field lang\/en\/api.php describes as\n\u00abthe number as it is now\u00bb on `channel.quality_changed`, and the\none App\\Services\\WebhookEmitter documents the supported use of:\npause marketing on RED, resume on GREEN. The column has held values that are neither. Meta's own Graph\nfield answers `UNKNOWN` for a number it has not rated, and until\nApp\\Jobs\\ProcessProviderWebhookChange::applyQuality() learned to\ntell Meta's two vocabularies apart it wrote the messaging TIER\nhere \u2014 so rows still read `TIER_1K`, and the nightly re-read that\nwould correct them never runs for a channel Meta has already\nbanned. Publishing those verbatim gave an integrator a value that\nmatches neither documented branch while looking like an answer,\nso their marketing kept flowing onto a flagged number. Null says\n\"we do not know\", which is a thing their code can be written\nagainst; `TIER_1K` in a quality field is not."
                                                },
                                                "messaging_tier": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "tier_limit": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "| NULL FOR A CHANNEL THAT HAS NO META TIER, and that is not a\n| tidying-up. Channel::tierLimit() falls back to TIER_250 for a null\n| `messaging_tier` \u2014 deliberately, and its own docblock says the\n| fallback \"is NOT a claim that Telegram has a 250-recipient limit\".\n| Published as a number it became exactly that claim: an integrator\n| batching against `tier_limit` capped a Telegram bot, which has no\n| such ceiling at all, at Meta's starter tier.\n|\n| The per-send doors already asked this question \u2014 TierBudget's\n| reserve() and admitDispatch() both guard on hasMessagingTier() \u2014\n| and the readers that only DISPLAY the number did not."
                                                },
                                                "sendable": {
                                                    "type": "boolean",
                                                    "description": "The question an integrator is actually asking when they call\n\/v1\/channels: not \"is it connected\" but \"can I send from it right\n now\". A connected number that Meta rate-limited an hour ago\nanswers yes to the first and no to this one."
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "type",
                                                "status",
                                                "provider_channel_id",
                                                "address",
                                                "verified_name",
                                                "quality_rating",
                                                "messaging_tier",
                                                "tier_limit",
                                                "sendable",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/contacts": {
            "get": {
                "operationId": "v1.contacts.index",
                "tags": [
                    "Contact"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "page": {
                                                    "type": "integer"
                                                },
                                                "per_page": {
                                                    "type": "integer"
                                                },
                                                "total": {
                                                    "type": "integer"
                                                },
                                                "last_page": {
                                                    "type": "integer"
                                                }
                                            },
                                            "required": [
                                                "page",
                                                "per_page",
                                                "total",
                                                "last_page"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "v1.contacts.store",
                "tags": [
                    "Contact"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "msisdn": {
                                        "type": "string",
                                        "maxLength": 32
                                    },
                                    "name": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 120
                                    },
                                    "list_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "opted_in": {
                                        "type": "boolean"
                                    }
                                },
                                "required": [
                                    "msisdn"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/contacts\/{contact}": {
            "get": {
                "operationId": "v1.contacts.show",
                "tags": [
                    "Contact"
                ],
                "parameters": [
                    {
                        "name": "contact",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "msisdn": {
                                                    "type": "string"
                                                },
                                                "name": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "country": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "source": {
                                                    "type": "string"
                                                },
                                                "can_receive": {
                                                    "type": "boolean",
                                                    "description": "The field an integrator must branch on before adding somebody to\nan audience. Opt-out is the one consent signal this platform can\nenforce, and it is the one Meta bans numbers over."
                                                },
                                                "opted_out_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "blocked": {
                                                    "type": "boolean"
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "msisdn",
                                                "name",
                                                "country",
                                                "source",
                                                "can_receive",
                                                "opted_out_at",
                                                "blocked",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "v1.contacts.destroy",
                "description": "THE PERSON GOES; THE RECORD OF WHAT THEY ASKED FOR DOES NOT. Consent\nlives on `recipient_permissions`, keyed by (account, provider, msisdn)\nand not by this row, so deleting a contact cannot destroy the fact that\nthey opted out. That is the whole reason it is keyed that way: a caller\nwho deletes a number and re-imports it tomorrow must not get a clean\nslate, because the person on the other end did not change their mind \u2014\nand a platform that messages them again is a reported number.\n\nThe audit trail survives for the same reason. `campaign_recipients` holds\nthe msisdn it actually sent to and only a NULLABLE reference to this row,\nso a finished campaign's report still says who was messaged and what it\ncost after the contact is gone.\n\n204, with no body. There is nothing left to present, and an integration\nthat deletes the same id twice gets 404 the second time \u2014 which is the\ntruth rather than a pretence that the delete happened again.",
                "summary": "Remove somebody from the address book",
                "tags": [
                    "Contact"
                ],
                "parameters": [
                    {
                        "name": "contact",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    }
                }
            }
        },
        "\/v1\/contact-imports": {
            "get": {
                "operationId": "v1.contact-imports.index",
                "tags": [
                    "ContactImport"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "page": {
                                                    "type": "integer"
                                                },
                                                "per_page": {
                                                    "type": "integer"
                                                },
                                                "total": {
                                                    "type": "integer"
                                                },
                                                "last_page": {
                                                    "type": "integer"
                                                }
                                            },
                                            "required": [
                                                "page",
                                                "per_page",
                                                "total",
                                                "last_page"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "v1.contact-imports.store",
                "tags": [
                    "ContactImport"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "multipart\/form-data": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "file": {
                                        "type": "string",
                                        "format": "binary",
                                        "contentMediaType": "application\/octet-stream",
                                        "description": "`mimes:csv,txt` rather than a content-type check alone: HTTP\nclients report CSV under at least four different types depending\non the platform, and an integration that gets a 422 for sending\nthe right file under the wrong header has no way to tell."
                                    },
                                    "contact_list_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "default_country": {
                                        "type": "string",
                                        "description": "Required, and deliberately not defaulted from the account: it is\nthe anchor a national-format number is read against, and a wrong\ndefault means messaging the right digits in the wrong country and\nbilling the customer at that country's rate. A caller whose file\nis all E.164 loses nothing by stating it.",
                                        "minLength": 2,
                                        "maxLength": 2
                                    }
                                },
                                "required": [
                                    "file",
                                    "default_country"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "original_name": {
                                                    "type": "string"
                                                },
                                                "contact_list_id": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "default_country": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string"
                                                },
                                                "progress_percent": {
                                                    "type": "integer"
                                                },
                                                "total_rows": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "processed_rows": {
                                                    "type": "integer"
                                                },
                                                "imported_rows": {
                                                    "type": "integer"
                                                },
                                                "updated_rows": {
                                                    "type": "integer"
                                                },
                                                "rejected_rows": {
                                                    "type": "integer"
                                                },
                                                "rejections": {
                                                    "type": "array",
                                                    "description": "Every refusal with the LINE NUMBER that caused it. This is the\nwhole reason the import writes a receipt: a customer who is told\n\u00ab140 rows rejected\u00bb and nothing else cannot fix their file, and a\ncustomer told nothing at all campaigns to 9,860 of 10,000 people\nand never learns which 140 were missed.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "line": {
                                                                "type": "integer"
                                                            },
                                                            "value": {
                                                                "type": "string"
                                                            },
                                                            "reason": {
                                                                "type": "string"
                                                            }
                                                        },
                                                        "required": [
                                                            "line",
                                                            "value",
                                                            "reason"
                                                        ]
                                                    }
                                                },
                                                "rejections_not_listed": {
                                                    "type": "integer",
                                                    "description": "The bounded list above is capped, so a caller rendering it has to\nbe able to say \u00aband N more\u00bb rather than imply the list is whole."
                                                },
                                                "started_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "finished_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "original_name",
                                                "contact_list_id",
                                                "default_country",
                                                "status",
                                                "progress_percent",
                                                "total_rows",
                                                "processed_rows",
                                                "imported_rows",
                                                "updated_rows",
                                                "rejected_rows",
                                                "rejections",
                                                "rejections_not_listed",
                                                "started_at",
                                                "finished_at",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/contact-imports\/{import}": {
            "get": {
                "operationId": "v1.contact-imports.show",
                "tags": [
                    "ContactImport"
                ],
                "parameters": [
                    {
                        "name": "import",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "original_name": {
                                                    "type": "string"
                                                },
                                                "contact_list_id": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "default_country": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "status": {
                                                    "type": "string"
                                                },
                                                "progress_percent": {
                                                    "type": "integer"
                                                },
                                                "total_rows": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "processed_rows": {
                                                    "type": "integer"
                                                },
                                                "imported_rows": {
                                                    "type": "integer"
                                                },
                                                "updated_rows": {
                                                    "type": "integer"
                                                },
                                                "rejected_rows": {
                                                    "type": "integer"
                                                },
                                                "rejections": {
                                                    "type": "array",
                                                    "description": "Every refusal with the LINE NUMBER that caused it. This is the\nwhole reason the import writes a receipt: a customer who is told\n\u00ab140 rows rejected\u00bb and nothing else cannot fix their file, and a\ncustomer told nothing at all campaigns to 9,860 of 10,000 people\nand never learns which 140 were missed.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "line": {
                                                                "type": "integer"
                                                            },
                                                            "value": {
                                                                "type": "string"
                                                            },
                                                            "reason": {
                                                                "type": "string"
                                                            }
                                                        },
                                                        "required": [
                                                            "line",
                                                            "value",
                                                            "reason"
                                                        ]
                                                    }
                                                },
                                                "rejections_not_listed": {
                                                    "type": "integer",
                                                    "description": "The bounded list above is capped, so a caller rendering it has to\nbe able to say \u00aband N more\u00bb rather than imply the list is whole."
                                                },
                                                "started_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "finished_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "original_name",
                                                "contact_list_id",
                                                "default_country",
                                                "status",
                                                "progress_percent",
                                                "total_rows",
                                                "processed_rows",
                                                "imported_rows",
                                                "updated_rows",
                                                "rejected_rows",
                                                "rejections",
                                                "rejections_not_listed",
                                                "started_at",
                                                "finished_at",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/lists": {
            "get": {
                "operationId": "v1.lists.index",
                "tags": [
                    "ContactList"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "page": {
                                                    "type": "integer"
                                                },
                                                "per_page": {
                                                    "type": "integer"
                                                },
                                                "total": {
                                                    "type": "integer"
                                                },
                                                "last_page": {
                                                    "type": "integer"
                                                }
                                            },
                                            "required": [
                                                "page",
                                                "per_page",
                                                "total",
                                                "last_page"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "v1.lists.store",
                "tags": [
                    "ContactList"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 120
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 255
                                    }
                                },
                                "required": [
                                    "name"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "description": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "contacts_count": {
                                                    "type": "integer"
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "name",
                                                "description",
                                                "contacts_count",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/lists\/{list}": {
            "get": {
                "operationId": "v1.lists.show",
                "tags": [
                    "ContactList"
                ],
                "parameters": [
                    {
                        "name": "list",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "description": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "contacts_count": {
                                                    "type": "integer"
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "name",
                                                "description",
                                                "contacts_count",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "v1.lists.destroy",
                "description": "THE CONTACTS SURVIVE IT. The pivot cascades, the people do not: a list is\na saved selection, and deleting a selection must never delete the address\nbook it was selected from.\n\nA LIST A LIVE CAMPAIGN IS SENDING FROM IS REFUSED. Not because deleting\nit would break the send \u2014 the audience is frozen onto\n`campaign_recipients` at launch and the campaign finishes either way \u2014\nbut because the report would lose the name of what it was built from, and\nan operator looking at a half-finished campaign should not have to guess.\n409 rather than 422: the request is well-formed and the world is not\nready for it, which is a state the caller can wait out.",
                "summary": "Delete a list",
                "tags": [
                    "ContactList"
                ],
                "parameters": [
                    {
                        "name": "list",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "No content"
                    },
                    "409": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/lists\/{list}\/contacts": {
            "post": {
                "operationId": "v1.lists.attach",
                "description": "syncWithoutDetaching, so a sync that sends today's members does not\nsilently empty the list of everybody it did not mention \u2014 which is how an\nintegration that paginates its own source ends up mailing a tenth of the\naudience it meant to.",
                "summary": "Put contacts on the list",
                "tags": [
                    "ContactList"
                ],
                "parameters": [
                    {
                        "name": "list",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "contact_ids": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer"
                                        },
                                        "minItems": 1
                                    }
                                },
                                "required": [
                                    "contact_ids"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "description": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "contacts_count": {
                                                    "type": "integer"
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "name",
                                                "description",
                                                "contacts_count",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/lists\/{list}\/contacts\/{contact}": {
            "delete": {
                "operationId": "v1.lists.detach",
                "description": "DETACH, NEVER DELETE. A contact is on several lists and holds the consent\nrecord for their number; removing them from an audience must not destroy\nthe fact that they opted out, or the next import puts them straight back\nand the platform messages somebody who asked it not to.\n\nBoth ids are resolved through the account first, so detaching somebody\nfrom another tenant's list is a 404 rather than an edit to their audience.",
                "summary": "Take one person off an audience",
                "tags": [
                    "ContactList"
                ],
                "parameters": [
                    {
                        "name": "list",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "contact",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "description": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "contacts_count": {
                                                    "type": "integer"
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "name",
                                                "description",
                                                "contacts_count",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/me": {
            "get": {
                "operationId": "v1.me",
                "tags": [
                    "Me"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "account": {
                                                    "type": "object",
                                                    "properties": {
                                                        "id": {
                                                            "type": "integer"
                                                        },
                                                        "name": {
                                                            "type": "string"
                                                        },
                                                        "slug": {
                                                            "type": "string"
                                                        },
                                                        "status": {
                                                            "type": "string"
                                                        },
                                                        "can_send": {
                                                            "type": "boolean"
                                                        },
                                                        "country": {
                                                            "type": [
                                                                "string",
                                                                "null"
                                                            ]
                                                        },
                                                        "timezone": {
                                                            "type": "string"
                                                        },
                                                        "plan": {
                                                            "type": "string"
                                                        }
                                                    },
                                                    "required": [
                                                        "id",
                                                        "name",
                                                        "slug",
                                                        "status",
                                                        "can_send",
                                                        "country",
                                                        "timezone",
                                                        "plan"
                                                    ]
                                                },
                                                "credential": {
                                                    "type": "object",
                                                    "properties": {
                                                        "id": {
                                                            "type": "integer"
                                                        },
                                                        "name": {
                                                            "type": "string"
                                                        },
                                                        "last_four": {
                                                            "type": "string"
                                                        },
                                                        "environment": {
                                                            "type": "string"
                                                        },
                                                        "scopes": {
                                                            "type": "array",
                                                            "items": {}
                                                        },
                                                        "expires_at": {
                                                            "type": [
                                                                "string",
                                                                "null"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "id",
                                                        "name",
                                                        "last_four",
                                                        "environment",
                                                        "scopes",
                                                        "expires_at"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "account",
                                                "credential"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/messages": {
            "get": {
                "operationId": "v1.messages.index",
                "tags": [
                    "Message"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "page": {
                                                    "type": "integer"
                                                },
                                                "per_page": {
                                                    "type": "integer"
                                                },
                                                "total": {
                                                    "type": "integer"
                                                },
                                                "last_page": {
                                                    "type": "integer"
                                                }
                                            },
                                            "required": [
                                                "page",
                                                "per_page",
                                                "total",
                                                "last_page"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "v1.messages.store",
                "tags": [
                    "Message"
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "A unique string for THIS call. The same key with the same body replays the first answer and does nothing twice; a different body under the same key is refused. A UUID per call is the usual choice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "to": {
                                        "type": "string",
                                        "maxLength": 32
                                    },
                                    "template_id": {
                                        "type": "integer"
                                    },
                                    "channel_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "variables": {
                                        "type": [
                                            "array",
                                            "null"
                                        ],
                                        "items": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "maxLength": 1024
                                        }
                                    }
                                },
                                "required": [
                                    "to",
                                    "template_id"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Nothing the caller can fix: their account's rate card chain has a\nhole in it. A 500 says so honestly instead of blaming the request.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "402, the one status that exists for exactly this. An integrator\nwho sees it knows the remedy is money and not a retry.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Two calls raced the same key and the loser's claim was refused by\nthe index while the winner has not finished creating its message.\nNot a conflict \u2014 the payloads may well match \u2014 just too early.\n\nA connected number Meta rate-limited an hour ago is not sendable.\nDiscovering that at Graph costs a charge, a refund and an attempt\nagainst a quality rating that is already the problem.\n\n\n\nMeta's template namespace is per WABA, so a template approved for\none number is not sendable from another \u2014 and sending it produces\na definite refusal AFTER the charge.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "schema": {
                                    "type": "string",
                                    "const": "1"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/messages\/{message}": {
            "get": {
                "operationId": "v1.messages.show",
                "tags": [
                    "Message"
                ],
                "parameters": [
                    {
                        "name": "message",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "channel_id": {
                                                    "type": "integer"
                                                },
                                                "template_id": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "direction": {
                                                    "type": "string"
                                                },
                                                "to": {
                                                    "type": "string",
                                                    "description": "E.164 digits with the plus restored. The column stores digits so\nthat a comparison never depends on formatting; the API returns\nthe form a human dials."
                                                },
                                                "status": {
                                                    "type": "string"
                                                },
                                                "dispatch_state": {
                                                    "type": "string",
                                                    "description": "OUR view of the attempt, alongside Meta's view of the message.\n`quarantined` is the state that makes this field necessary: the\nmessage may well have been delivered, and no single value can say\n\"we do not know\" and \"queued\" at once."
                                                },
                                                "provider_message_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "billing_category": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "price_microusd": {
                                                    "type": "integer"
                                                },
                                                "price": {
                                                    "type": "string"
                                                },
                                                "error": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "error_code": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "refunded": {
                                                    "type": "boolean"
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "dispatched_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "channel_id",
                                                "template_id",
                                                "direction",
                                                "to",
                                                "status",
                                                "dispatch_state",
                                                "provider_message_id",
                                                "billing_category",
                                                "price_microusd",
                                                "price",
                                                "error",
                                                "error_code",
                                                "refunded",
                                                "created_at",
                                                "dispatched_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/rates": {
            "get": {
                "operationId": "v1.rates",
                "tags": [
                    "Rate"
                ],
                "parameters": [
                    {
                        "name": "channel",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "enum": [
                                "whatsapp",
                                "telegram",
                                null
                            ]
                        }
                    },
                    {
                        "name": "category",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "enum": [
                                "marketing",
                                "utility",
                                "authentication",
                                "service",
                                null
                            ]
                        }
                    },
                    {
                        "name": "market",
                        "in": "query",
                        "description": "Either a market, or a real number to derive one from. `to` is the\nuseful one in practice: an integrator holds phone numbers, not\nISO codes, and asking them to map one to the other is asking them\nto reimplement our dial-prefix table.",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "minLength": 2,
                            "maxLength": 2
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "schema": {
                            "type": [
                                "string",
                                "null"
                            ],
                            "maxLength": 32
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "channel": {
                                                        "type": "string"
                                                    },
                                                    "category": {
                                                        "type": "string"
                                                    },
                                                    "market": {
                                                        "type": "string"
                                                    },
                                                    "matched_market": {
                                                        "type": "string",
                                                        "description": "The row that actually priced it. When a customer asks why two\nmarkets cost the same, \"both matched the '*' row\" is an answer\nand a bare number is not."
                                                    },
                                                    "price_microusd": {
                                                        "type": "integer"
                                                    },
                                                    "price": {
                                                        "type": "string"
                                                    },
                                                    "currency": {
                                                        "type": "string"
                                                    }
                                                },
                                                "required": [
                                                    "channel",
                                                    "category",
                                                    "market",
                                                    "matched_market",
                                                    "price_microusd",
                                                    "price",
                                                    "currency"
                                                ]
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "channel": {
                                                    "type": "string"
                                                },
                                                "market": {
                                                    "type": "string"
                                                }
                                            },
                                            "required": [
                                                "channel",
                                                "market"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Every category missing means the account's whole card chain is\nbroken, which is ours to fix and not something the caller can act\non \u2014 so it is a server error, loudly, rather than an empty list\nthat reads like \"everything is free\".",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/templates": {
            "get": {
                "operationId": "v1.templates.index",
                "tags": [
                    "Template"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "page": {
                                                    "type": "integer"
                                                },
                                                "per_page": {
                                                    "type": "integer"
                                                },
                                                "total": {
                                                    "type": "integer"
                                                },
                                                "last_page": {
                                                    "type": "integer"
                                                }
                                            },
                                            "required": [
                                                "page",
                                                "per_page",
                                                "total",
                                                "last_page"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "v1.templates.store",
                "description": "Two decisions in one call, because they are one decision to the caller:\nsave it, and optionally send it into review. `submit_for_review` defaults\nto true here where the console screen defaults to false \u2014 an integration\nhas no \"come back and click submit later\", and a draft nobody can reach\nis a template that never sends.",
                "summary": "File a new template",
                "tags": [
                    "Template"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "channel_id": {
                                        "type": "integer"
                                    },
                                    "name": {
                                        "type": "string",
                                        "maxLength": 191
                                    },
                                    "language": {
                                        "type": "string",
                                        "maxLength": 16
                                    },
                                    "category": {
                                        "type": "string",
                                        "enum": [
                                            "MARKETING",
                                            "UTILITY",
                                            "AUTHENTICATION"
                                        ]
                                    },
                                    "body": {
                                        "type": "string",
                                        "maxLength": 1024
                                    },
                                    "header_text": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 60
                                    },
                                    "footer": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 60
                                    },
                                    "opt_out_button": {
                                        "type": [
                                            "boolean",
                                            "null"
                                        ]
                                    },
                                    "submit_for_review": {
                                        "type": [
                                            "boolean",
                                            "null"
                                        ]
                                    }
                                },
                                "required": [
                                    "channel_id",
                                    "name",
                                    "language",
                                    "category",
                                    "body"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "channel_id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "language": {
                                                    "type": "string"
                                                },
                                                "category": {
                                                    "type": "string"
                                                },
                                                "effective_category": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "What Meta will BILL at, which is not always what was asked for.\nAn integrator estimating a campaign's cost needs this one, and\nthe gap between the two fields is the surprise on the invoice."
                                                },
                                                "status": {
                                                    "type": "string"
                                                },
                                                "usable": {
                                                    "type": "boolean"
                                                },
                                                "body": {
                                                    "type": "string"
                                                },
                                                "variables": {
                                                    "type": "integer"
                                                },
                                                "rejection_reason": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "channel_id",
                                                "name",
                                                "language",
                                                "category",
                                                "effective_category",
                                                "status",
                                                "usable",
                                                "body",
                                                "variables",
                                                "rejection_reason",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/templates\/{template}": {
            "get": {
                "operationId": "v1.templates.show",
                "tags": [
                    "Template"
                ],
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "channel_id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "language": {
                                                    "type": "string"
                                                },
                                                "category": {
                                                    "type": "string"
                                                },
                                                "effective_category": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "What Meta will BILL at, which is not always what was asked for.\nAn integrator estimating a campaign's cost needs this one, and\nthe gap between the two fields is the surprise on the invoice."
                                                },
                                                "status": {
                                                    "type": "string"
                                                },
                                                "usable": {
                                                    "type": "boolean"
                                                },
                                                "body": {
                                                    "type": "string"
                                                },
                                                "variables": {
                                                    "type": "integer"
                                                },
                                                "rejection_reason": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "channel_id",
                                                "name",
                                                "language",
                                                "category",
                                                "effective_category",
                                                "status",
                                                "usable",
                                                "body",
                                                "variables",
                                                "rejection_reason",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/templates\/{template}\/submit": {
            "post": {
                "operationId": "v1.templates.submit",
                "summary": "Hand an existing draft to the review queue",
                "tags": [
                    "Template"
                ],
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "channel_id": {
                                                    "type": "integer"
                                                },
                                                "name": {
                                                    "type": "string"
                                                },
                                                "language": {
                                                    "type": "string"
                                                },
                                                "category": {
                                                    "type": "string"
                                                },
                                                "effective_category": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "What Meta will BILL at, which is not always what was asked for.\nAn integrator estimating a campaign's cost needs this one, and\nthe gap between the two fields is the surprise on the invoice."
                                                },
                                                "status": {
                                                    "type": "string"
                                                },
                                                "usable": {
                                                    "type": "boolean"
                                                },
                                                "body": {
                                                    "type": "string"
                                                },
                                                "variables": {
                                                    "type": "integer"
                                                },
                                                "rejection_reason": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "channel_id",
                                                "name",
                                                "language",
                                                "category",
                                                "effective_category",
                                                "status",
                                                "usable",
                                                "body",
                                                "variables",
                                                "rejection_reason",
                                                "created_at"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A template that is already submitted, approved or rejected. 409\nrather than 422: nothing about the request is malformed, the\nresource is simply not in a state where this makes sense.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/webhooks": {
            "get": {
                "operationId": "v1.webhooks.index",
                "tags": [
                    "WebhookEndpoint"
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {}
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "page": {
                                                    "type": "integer"
                                                },
                                                "per_page": {
                                                    "type": "integer"
                                                },
                                                "total": {
                                                    "type": "integer"
                                                },
                                                "last_page": {
                                                    "type": "integer"
                                                }
                                            },
                                            "required": [
                                                "page",
                                                "per_page",
                                                "total",
                                                "last_page"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data",
                                        "meta"
                                    ]
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "v1.webhooks.store",
                "tags": [
                    "WebhookEndpoint"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "maxLength": 2048
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 191
                                    },
                                    "events": {
                                        "type": "array",
                                        "items": {
                                            "type": "string",
                                            "maxLength": 64
                                        },
                                        "minItems": 1
                                    }
                                },
                                "required": [
                                    "url",
                                    "events"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The one and only time this value leaves the building.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "url": {
                                                    "type": "string"
                                                },
                                                "description": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "events": {
                                                    "type": "array",
                                                    "items": {}
                                                },
                                                "enabled": {
                                                    "type": "boolean"
                                                },
                                                "disabled_reason": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "consecutive_failures": {
                                                    "type": "integer"
                                                },
                                                "last_status": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "last_error": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last_success_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last_failure_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "secret_rotated_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "secret": {
                                                    "type": "string"
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "url",
                                                "description",
                                                "events",
                                                "enabled",
                                                "disabled_reason",
                                                "consecutive_failures",
                                                "last_status",
                                                "last_error",
                                                "last_success_at",
                                                "last_failure_at",
                                                "secret_rotated_at",
                                                "created_at",
                                                "secret"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/webhooks\/{endpoint}": {
            "patch": {
                "operationId": "v1.webhooks.update",
                "tags": [
                    "WebhookEndpoint"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application\/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 2048
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 191
                                    },
                                    "events": {
                                        "type": [
                                            "array",
                                            "null"
                                        ],
                                        "items": {
                                            "type": "string",
                                            "maxLength": 64
                                        },
                                        "minItems": 1
                                    },
                                    "enabled": {
                                        "type": [
                                            "boolean",
                                            "null"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "url": {
                                                    "type": "string"
                                                },
                                                "description": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "events": {
                                                    "type": "array",
                                                    "items": {}
                                                },
                                                "enabled": {
                                                    "type": "boolean"
                                                },
                                                "disabled_reason": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "consecutive_failures": {
                                                    "type": "integer"
                                                },
                                                "last_status": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "last_error": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last_success_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last_failure_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "secret_rotated_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "secret": {
                                                    "type": "null"
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "url",
                                                "description",
                                                "events",
                                                "enabled",
                                                "disabled_reason",
                                                "consecutive_failures",
                                                "last_status",
                                                "last_error",
                                                "last_success_at",
                                                "last_failure_at",
                                                "secret_rotated_at",
                                                "created_at",
                                                "secret"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The request could not be accepted as sent.",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "$ref": "#\/components\/schemas\/MasarValidationError"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "v1.webhooks.destroy",
                "tags": [
                    "WebhookEndpoint"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean"
                                                }
                                            },
                                            "required": [
                                                "deleted"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/webhooks\/{endpoint}\/rotate-secret": {
            "post": {
                "operationId": "v1.webhooks.rotate",
                "description": "The old secret does NOT stop working here. Deliveries carry a signature\nunder both until the customer explicitly retires the old one, which is\nthe whole of zero-downtime rotation \u2014 see WebhookEndpoint::rotateSecret().",
                "summary": "Mint a new signing secret and keep the old one live",
                "tags": [
                    "WebhookEndpoint"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "url": {
                                                    "type": "string"
                                                },
                                                "description": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "events": {
                                                    "type": "array",
                                                    "items": {}
                                                },
                                                "enabled": {
                                                    "type": "boolean"
                                                },
                                                "disabled_reason": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "consecutive_failures": {
                                                    "type": "integer"
                                                },
                                                "last_status": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "last_error": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last_success_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last_failure_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "secret_rotated_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "secret": {
                                                    "type": "string"
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "url",
                                                "description",
                                                "events",
                                                "enabled",
                                                "disabled_reason",
                                                "consecutive_failures",
                                                "last_status",
                                                "last_error",
                                                "last_success_at",
                                                "last_failure_at",
                                                "secret_rotated_at",
                                                "created_at",
                                                "secret"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/webhooks\/{endpoint}\/retire-secret": {
            "post": {
                "operationId": "v1.webhooks.retire-secret",
                "summary": "Finish a rotation: the previous secret stops being sent",
                "tags": [
                    "WebhookEndpoint"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "url": {
                                                    "type": "string"
                                                },
                                                "description": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "events": {
                                                    "type": "array",
                                                    "items": {}
                                                },
                                                "enabled": {
                                                    "type": "boolean"
                                                },
                                                "disabled_reason": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "consecutive_failures": {
                                                    "type": "integer"
                                                },
                                                "last_status": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ]
                                                },
                                                "last_error": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last_success_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "last_failure_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "secret_rotated_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                },
                                                "secret": {
                                                    "type": "null"
                                                }
                                            },
                                            "required": [
                                                "id",
                                                "url",
                                                "description",
                                                "events",
                                                "enabled",
                                                "disabled_reason",
                                                "consecutive_failures",
                                                "last_status",
                                                "last_error",
                                                "last_success_at",
                                                "last_failure_at",
                                                "secret_rotated_at",
                                                "created_at",
                                                "secret"
                                            ]
                                        }
                                    },
                                    "required": [
                                        "data"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "\/v1\/webhooks\/{endpoint}\/test": {
            "post": {
                "operationId": "v1.webhooks.test",
                "description": "Synchronous, and it does not count against the failure counter. A\ncustomer testing a receiver they are still writing would otherwise\nauto-disable their own endpoint before it ever went live.",
                "summary": "Send one signed delivery right now and report what happened",
                "tags": [
                    "WebhookEndpoint"
                ],
                "parameters": [
                    {
                        "name": "endpoint",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "",
                        "content": {
                            "application\/json": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "description": "Use Authorization: Bearer <Masar API key>.",
                "scheme": "bearer",
                "bearerFormat": "Masar API key"
            }
        },
        "schemas": {
            "MasarError": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "object",
                        "properties": {
                            "code": {
                                "type": "string",
                                "description": "A stable machine code. Branch on THIS, never on the HTTP status or the message: two refusals often share a status and have opposite remedies, and the message is translated and may be rewritten."
                            },
                            "message": {
                                "type": "string",
                                "description": "A sentence for a human, in the caller account's language."
                            },
                            "request_id": {
                                "type": "string",
                                "description": "Also on the Masar-Request-Id header of every response. Quoted in a support request it resolves to exactly one call in the request log."
                            }
                        },
                        "required": [
                            "code",
                            "message"
                        ]
                    }
                },
                "required": [
                    "error"
                ],
                "title": "MasarError"
            },
            "MasarValidationError": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "object",
                        "properties": {
                            "code": {
                                "type": "string",
                                "description": "Always `validation_failed`."
                            },
                            "message": {
                                "type": "string"
                            },
                            "request_id": {
                                "type": "string"
                            },
                            "errors": {
                                "type": "object",
                                "description": "Field name to the list of things wrong with it. A header the endpoint requires appears here under its own name \u2014 `Idempotency-Key`, for example."
                            }
                        },
                        "required": [
                            "code",
                            "message"
                        ]
                    }
                },
                "required": [
                    "error"
                ],
                "title": "MasarValidationError"
            }
        },
        "responses": {
            "ValidationException": {
                "description": "Validation error",
                "content": {
                    "application\/json": {
                        "schema": {
                            "type": "object",
                            "properties": {
                                "message": {
                                    "type": "string",
                                    "description": "Errors overview."
                                },
                                "errors": {
                                    "type": "object",
                                    "description": "A detailed description of each field that failed validation.",
                                    "additionalProperties": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        }
                                    }
                                }
                            },
                            "required": [
                                "message",
                                "errors"
                            ]
                        }
                    }
                }
            }
        }
    }
}