{
  "openapi": "3.0.0",
  "info": {
    "title": "Textable Backend API",
    "version": "7.4.15@99c40ebc"
  },
  "servers": [
    {
      "url": "https://{project-id}.textable.app/",
      "description": "White Label Instance URL"
    },
    {
      "url": "https://api.textable.app/",
      "description": "Textable (Retail) URL"
    },
    {
      "url": "https://sandbox.textable.app/",
      "description": "White Label API Sandbox URL"
    }
  ],
  "components": {
    "schemas": {
      "Drip": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "drips": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "APIError": {
        "type": "object",
        "properties": {
          "_errType": {
            "type": "string",
            "enum": [
              "TXBDEV_API_ERROR_V1"
            ],
            "description": "A string identifying the error type"
          },
          "message": {
            "type": "string",
            "description": "A human-readable message providing more details about the error"
          },
          "referenceCode": {
            "type": "string",
            "description": "A unique identifier for the error instance"
          }
        }
      },
      "APIErrorTenantAdminAlreadyExistsTenant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID of the tenant"
          },
          "name": {
            "type": "string",
            "description": "Name of the tenant"
          },
          "externalId": {
            "type": "string",
            "description": "External ID of the tenant"
          }
        }
      },
      "APIErrorTenantAdminAlreadyExists": {
        "allOf": [
          {
            "$ref": "#/components/schemas/APIError"
          },
          {
            "type": "object",
            "properties": {
              "additionalContext": {
                "type": "object",
                "properties": {
                  "user": {
                    "type": "object",
                    "description": "Details about the user that was found",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "ID of the user"
                      },
                      "externalId": {
                        "type": "string",
                        "description": "External ID of the user"
                      },
                      "tenant": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/APIErrorTenantAdminAlreadyExistsTenant"
                          },
                          {
                            "type": "object",
                            "description": "Details about the tenant to which the user was found to belong"
                          }
                        ]
                      }
                    }
                  },
                  "requestedTenant": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/APIErrorTenantAdminAlreadyExistsTenant"
                      },
                      {
                        "type": "object",
                        "description": "Details about the tenant to which the user was requested to be added"
                      }
                    ]
                  }
                }
              }
            }
          }
        ]
      },
      "PublicTextableUser": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The user's ID"
          },
          "is_disabled": {
            "type": "boolean",
            "description": "Whether the user is disabled"
          },
          "full_name": {
            "type": "string",
            "description": "The user's full name"
          },
          "email": {
            "type": "string",
            "description": "The user's email address"
          },
          "organizationId": {
            "type": "string",
            "description": "The user's organization ID"
          },
          "phone_number": {
            "type": "string",
            "description": "The user's phone number"
          },
          "sharedWith": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of IDs; one for each user with whom this user is shared"
          },
          "deleted": {
            "type": "number",
            "description": "The timestamp the user was deleted"
          },
          "restrictions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The list of restrictions applied to the user"
          },
          "relayWebhook": {
            "type": "string",
            "description": "The user's relay webhook URL"
          },
          "autoReplyMessage": {
            "type": "string",
            "description": "The user's auto-reply message"
          },
          "signatureEnabled": {
            "type": "boolean",
            "description": "Whether the user's signature is enabled"
          },
          "signatureText": {
            "type": "string",
            "description": "The user's signature text"
          },
          "isAdmin": {
            "type": "boolean",
            "description": "Whether the user is an admin"
          },
          "provider": {
            "type": "string",
            "description": "The user's provider"
          }
        }
      },
      "ProviderAccess": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The name of the provider"
          },
          "credentials": {
            "type": "object",
            "description": "an object containing the necessary credentials to authenticate to the provider"
          }
        }
      }
    },
    "securitySchemes": {
      "FirebaseAuth": {
        "type": "apiKey",
        "description": "A short-lived Firebase Authentication token (managed by Firebase) corresponding to a user.  Routes secured with this scheme are generally only designed to be used by the frontend or mobile application, and should not be consumed by third party code.",
        "name": "Authorization",
        "scheme": "Bearer",
        "in": "header",
        "bearerFormat": "base64"
      },
      "UserToken": {
        "type": "apiKey",
        "description": "A long-lived token managed in-app by the user (or a plan administrator).  Supports use cases where API calls should be made in the context of the user. **Format:** Bearer accountUid:apiKey",
        "name": "Authorization",
        "scheme": "Bearer",
        "in": "header",
        "bearerFormat": "base64",
        "scopes": {
          "admin": "has `isAdmin` defined on the user owning the token"
        }
      },
      "SystemToken": {
        "type": "apiKey",
        "description": "A long-lived token managed by system administrators for the purpose of role-scoped operations by other systems.",
        "name": "Authorization",
        "scheme": "Bearer",
        "in": "header",
        "bearerFormat": "base64"
      }
    }
  },
  "x-tagGroups": [
    {
      "name": "API V1",
      "tags": [
        "apiv1-canned",
        "apiv1-drips",
        "apiv1-contacts",
        "apiv1-messages",
        "apiv1-orgs",
        "apiv1-users",
        "apiv1-other"
      ]
    },
    {
      "name": "API V2",
      "tags": [
        "apiv2-contacts",
        "apiv2-users",
        "apiv2-orgs",
        "apiv2-other",
        "apiv2-bulk",
        "apiv2-canned-responses",
        "apiv2-tenants",
        "apiv2-billing"
      ]
    },
    {
      "name": "API Beta",
      "tags": [
        "api-beta"
      ]
    },
    {
      "name": "Frontend Only",
      "tags": [
        "frontend"
      ]
    },
    {
      "name": "Miscellaneous",
      "tags": [
        "skyswitch-exclusive",
        "health"
      ]
    },
    {
      "name": "Authentication",
      "tags": [
        "SSO",
        "Service Accounts"
      ]
    },
    {
      "name": "Webhooks",
      "tags": [
        "webhooks"
      ]
    }
  ],
  "tags": [
    {
      "name": "webhooks",
      "x-displayName": "Webhooks"
    },
    {
      "name": "apiv1-canned",
      "x-displayName": "Canned Responses"
    },
    {
      "name": "apiv1-contacts",
      "x-displayName": "Contacts"
    },
    {
      "name": "apiv1-drips",
      "x-displayName": "Drip Campaigns"
    },
    {
      "name": "apiv1-messages",
      "x-displayName": "Messages"
    },
    {
      "name": "apiv1-users",
      "x-displayName": "Users"
    },
    {
      "name": "apiv1-orgs",
      "x-displayName": "Organizations"
    },
    {
      "name": "apiv1-other",
      "x-displayName": "Other"
    },
    {
      "name": "apiv2-contacts",
      "x-displayName": "Contacts"
    },
    {
      "name": "apiv2-users",
      "x-displayName": "Users"
    },
    {
      "name": "apiv2-orgs",
      "x-displayName": "Organizations"
    },
    {
      "name": "apiv2-other",
      "x-displayName": "Other"
    },
    {
      "name": "apiv2-bulk",
      "x-displayName": "Bulk Operations"
    },
    {
      "name": "apiv2-tenants",
      "x-displayName": "Tenants"
    },
    {
      "name": "apiv2-billing",
      "x-displayName": "Billing"
    },
    {
      "name": "frontend",
      "x-displayName": "Frontend",
      "description": "Do not use these routes.  The behavior is subject to change or be removed without notice.  See TXBDEV-2858 for more details"
    },
    {
      "name": "api-beta",
      "x-displayName": "API Beta",
      "description": "Behavior of routes in this group is subject to change or removal without changes to the major or minor version number"
    },
    {
      "name": "apiv2-canned-responses",
      "x-displayName": "Canned Responses"
    },
    {
      "name": "health",
      "x-displayName": "Health Check"
    },
    {
      "name": "skyswitch-exclusive",
      "x-displayName": "SkySwitch Exclusive"
    },
    {
      "name": "apiv2-provider-capabilities",
      "x-displayName": "Provider Capabilities"
    }
  ],
  "paths": {
    "/api/v2/document-schema/scan": {
      "post": {
        "tags": [
          "apiv2-other"
        ],
        "summary": "Start document schema validation",
        "description": "Initiates the document schema validation process.",
        "security": [
          {
            "FirebaseAuth": [
              "user"
            ]
          },
          {
            "UserToken": [
              "user"
            ]
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "uid",
            "required": false,
            "description": "Optionally constrains the schema validation to documents owned by this user ID.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Schema validation started"
          },
          "409": {
            "description": "Schema validation is already running"
          }
        }
      }
    },
    "/pbx/sms-enabled-assignments": {
      "get": {
        "tags": [
          "skyswitch-exclusive"
        ],
        "summary": "Gets SMS-enabled assignments",
        "description": "Gets SMS-enabled assignments for the current tenant from the SkySwitch PBX endpoint at https://telco.readme.io/v1.0/docs/list-sms-enabled-assignments",
        "security": [
          {
            "FirebaseAuth": []
          }
        ]
      }
    },
    "/skyswitch/pbx/get-assignment": {
      "get": {
        "tags": [
          "skyswitch-exclusive"
        ],
        "summary": "PBX number assignment to SkySwitch's telco API",
        "responses": {
          "200": {
            "description": "Returns the status from the PBX api"
          }
        }
      }
    },
    "/skyswitch/pbx/delete-assignment": {
      "post": {
        "tags": [
          "skyswitch-exclusive"
        ],
        "summary": "PBX number assignment to SkySwitch's telco API",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted the assignment from the PBX api"
          }
        }
      }
    },
    "/skyswitch/pbx/clickToCall": {
      "post": {
        "tags": [
          "skyswitch-exclusive"
        ],
        "summary": "Click to call SkySwitch API",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "destination": {
                    "type": "string"
                  },
                  "callAsUID": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Call made successfully"
          },
          "400": {
            "description": "Not authorized"
          },
          "403": {
            "descriotion": "The requested outbound phone number is not shared with the current user."
          },
          "500": {
            "description": "Unable to hit endpoint"
          }
        }
      }
    },
    "/api/beta/block": {
      "post": {
        "tags": [
          "api-beta"
        ],
        "summary": "Block a number from sending messages to the user",
        "description": "One or more contact block requests\n",
        "security": [
          {
            "FirebaseAuth": []
          },
          {
            "UserToken": []
          }
        ],
        "requestBody": {
          "description": "Array of contact block requests",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "action": {
                      "type": "string",
                      "description": "Action to take for the provided contact",
                      "enum": [
                        "block",
                        "unblock"
                      ],
                      "descriptions": {
                        "block": "Block the sender",
                        "unblock": "Unblock the sender.  Will not re-created deleted messages or contact records"
                      }
                    },
                    "sender": {
                      "type": "string",
                      "description": "Sender to block.  Can be either an E.164 phone number or a contact id"
                    },
                    "user": {
                      "type": "string",
                      "description": "User for which to apply the block operation. Can be either an E.164 phone number or a user id"
                    },
                    "options": {
                      "type": "object",
                      "properties": {
                        "sendStop": {
                          "type": "boolean",
                          "description": "Send a STOP message to the blocked sender.  If sending this message fails, errors will not be reported."
                        },
                        "delete": {
                          "type": "boolean",
                          "description": "Delete the contact record (if one exists) for the blocked sender"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The block operations were applied."
          },
          "401": {
            "description": "The API token is not authorized to perform the requested operation"
          },
          "404": {
            "description": "The user (specified by either a user id or phone number) was not found"
          },
          "500": {
            "description": "An unexpected error occurred.  Possibly multiple contacts for the requested user matching the provided phone number."
          }
        }
      }
    },
    "/api/beta/contacts": {
      "post": {
        "tags": [
          "api-beta"
        ],
        "summary": "Upload batches of Contacts",
        "description": "POST an array of contact operations.  The operation will be batched to the database, and the request will return once the batch is committed.\n",
        "security": [
          {
            "FirebaseAuth": []
          },
          {
            "UserToken": []
          }
        ],
        "requestBody": {
          "description": "An array of contact operations to perform",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contacts": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "action": {
                          "type": "string",
                          "enum": [
                            "create",
                            "update"
                          ],
                          "description": "The action to perform on the contact"
                        },
                        "id": {
                          "type": "string",
                          "description": "The contact document ID to update (required for update actions, omit for create actions)"
                        },
                        "data": {
                          "type": "object",
                          "description": "Contact data to create or update.  For update actions, only include fields to update.  \nFor array fields, use the special `arrayUnion` operation to add items to an array without overwriting the entire array.  Example:\n{\n  \"field1\": \"value1\",\n  \"field2\": {\n    \"_methodName\": \"arrayUnion\",\n    \"items\": [\"value2\", \"value3\"]\n  }\n}\n"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The contacts were comitted to the database",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "details": {
                      "type": "object",
                      "properties": {
                        "doneBatches": {
                          "type": "number"
                        },
                        "doneItems": {
                          "type": "number"
                        },
                        "totalBatches": {
                          "type": "number"
                        },
                        "totalItems": {
                          "type": "number"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The request included one or more contacts for which the requestor is unauthorized to modify.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "_errType": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "referenceCode": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/beta/deduplicate-contacts": {
      "post": {
        "tags": [
          "api-beta"
        ],
        "summary": "Search for and merge duplicate contacts",
        "description": "This endpoint is used to search for and merge duplicate contacts for the requesting user\n",
        "security": [
          {
            "FirebaseAuth": []
          },
          {
            "UserToken": []
          }
        ],
        "requestBody": {
          "description": "Parameters for the duplicate contact search / merge operation",
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "uid": {
                    "type": "string",
                    "description": "The user ID to search for duplicate contacts. \nIf not specified, the authenticated user's ID will be used.\n"
                  },
                  "execute_merge": {
                    "type": "boolean",
                    "description": "Whether to merge the duplicate contacts. \nIf not specified, the default is false.\n"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The request was successful and the contacts were merged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "duplicates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "phoneNumber": {
                            "type": "string",
                            "description": "The phone number of the duplicate contacts"
                          },
                          "count": {
                            "type": "integer",
                            "description": "The number of duplicate contacts found for the phone number"
                          }
                        }
                      }
                    },
                    "merged": {
                      "type": "boolean",
                      "description": "Whether the contacts were merged"
                    },
                    "errors": {
                      "type": "array",
                      "description": "An array of error messages",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request was invalid."
          },
          "401": {
            "description": "The request was unauthorized."
          },
          "500": {
            "description": "The server encountered an error processing the request."
          }
        }
      }
    },
    "/api/v2/provider-capabilities/did-suggestions/suggestions": {
      "post": {
        "summary": "Get DID suggestions",
        "description": "Provides a list of suggested DIDs based on the provided search criteria.\n",
        "tags": [
          "apiv2-provider-capabilities"
        ]
      }
    },
    "/api/v2/biling/tenantReport/:tenantId": {
      "get": {
        "tags": [
          "apiv2-billing"
        ],
        "summary": "Get Billing For a Tenant",
        "description": "Gets billing details for a single tenant",
        "security": [
          {
            "SystemToken": [
              "read-tenant-biling"
            ]
          }
        ],
        "parameters": [
          {
            "name": "tenantId",
            "in": "path",
            "required": true,
            "description": "The ID of the tenant for which to generate a billing report",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": null,
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/definitions/TenantBillingObject"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/biling/tenantReport": {
      "get": {
        "tags": [
          "apiv2-billing"
        ],
        "summary": "Get billing report for all tenants",
        "description": "Gets billing details for all tenants",
        "security": [
          {
            "SystemToken": [
              "read-tenant-biling"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": null,
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/definitions/TenantBillingObject"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/bulk/unread": {
      "post": {
        "tags": [
          "apiv2-bulk"
        ],
        "summary": "Mark as unread",
        "description": "API Route to mark a number of selected contact ids and set\nread_status to false.\n",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "requestBody": {
          "description": "Array of contact id strings.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contactsArray": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The contacts were marked as unread",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The contacts were marked as unread",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "boolean"
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/canned-responses": {
      "post": {
        "tags": [
          "apiv2-canned-responses"
        ],
        "summary": "Create a canned response.",
        "description": "Creates a canned response.\n",
        "security": [
          {
            "FirebaseAuth": [
              "user"
            ]
          },
          {
            "UserToken": [
              "user"
            ]
          }
        ],
        "requestBody": {
          "description": null,
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "uid": {
                    "type": "string",
                    "description": "The user id of the user to add the canned response for."
                  },
                  "name": {
                    "type": "string",
                    "description": "A friendly name to represent the canned response content."
                  },
                  "body": {
                    "type": "string",
                    "description": "The body of the canned response text message."
                  },
                  "auto_keyword": {
                    "type": "string",
                    "description": "A keyword that when received would trigger the canned response as an auto-reply."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Canned response has been created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The id of the newly created canned response."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "There was an error with creating the canned response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A description of the error that occurred."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "There was a server error when creating the canned response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A description of the error that occurred."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/contacts/{id}": {
      "patch": {
        "tags": [
          "apiv2-contacts"
        ],
        "summary": "Update Contact By Id",
        "description": "Updates a contact according to the attributes supplied.",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          }
        ],
        "requestBody": {
          "description": "the properties to update.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "full_name": {
                    "type": "string"
                  },
                  "phone_number": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "companyName": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "optedOut": {
                    "type": "boolean",
                    "description": "Sets Boolean value controling if the contact has opted out of communications"
                  },
                  "isArchived": {
                    "type": "boolean",
                    "description": "Sets the status of the contact and conversations to archived"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Contact has been updated."
          },
          "400": {
            "description": "The request was not properly formated and the contact failed to update"
          },
          "403": {
            "description": "Not Authorized to make change"
          },
          "500": {
            "description": "There was a server error while updating the contact"
          }
        }
      },
      "delete": {
        "tags": [
          "apiv2-contacts"
        ],
        "summary": "Delete Contact By Id",
        "description": "Deletes a contact by its unique identifier.",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          }
        ],
        "responses": {
          "204": {
            "description": "Contact has been deleted."
          },
          "403": {
            "description": "Not Authorized to make change"
          },
          "500": {
            "description": "There was a server error while deleting the contact"
          }
        }
      }
    },
    "/api/v2/contacts/{id}/drip": {
      "post": {
        "tags": [
          "apiv2-contacts"
        ],
        "summary": "Apply Drip Campaign to Contact",
        "description": "Applies a drip campaign to a contact.",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          }
        ],
        "requestBody": {
          "description": "the properties to update.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "dripCampaignId": {
                    "type": "string",
                    "description": "The ID of the drip campaign to apply to the contact"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Drip Campaign has been applied.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dripCampaignId": {
                      "type": "string",
                      "description": "The ID of the drip campaign that was applied"
                    },
                    "addedDripMessages": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The IDs of the messages that were created as part of the drip campaign"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request was not properly formated and the contact failed to update"
          },
          "403": {
            "description": "Not Authorized to make change"
          },
          "500": {
            "description": "There was a server error while updating the contact"
          }
        }
      }
    },
    "/api/v2/provider-capabilities/number-routing/set": {
      "post": {
        "summary": "Set number routing",
        "description": "Makes an API call to the specified messaging provider to configure\nSMS routing for the given phone number to the API URL of this instance\n",
        "tags": [
          "Number Routing"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "providerId": {
                    "type": "string"
                  },
                  "organizationId": {
                    "type": "string"
                  },
                  "phoneNumber": {
                    "type": "string"
                  },
                  "userId": {
                    "type": "string"
                  },
                  "tenantId": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Number routing set successfully"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal server error"
          }
        }
      }
    },
    "/api/v2/organizations/": {
      "get": {
        "tags": [
          "apiv2-orgs"
        ],
        "summary": "Get Organizations",
        "description": "Get all organizations.\n\nPresently only available to admins, as the results are not trimmed according to organizations\nwithin the user's management scope. \n\nTODO: TXBDEV-1916 - Allow tenant admin / org admin users to GET /api/v2/organizations\n",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "read-all-organizations"
            ]
          }
        ]
      }
    },
    "/api/v2/organizations/{id}": {
      "patch": {
        "tags": [
          "apiv2-orgs"
        ],
        "summary": "Update Organization",
        "description": "Updates an organization according to the attributes supplied.",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "edit-organizations"
            ]
          }
        ],
        "requestBody": {
          "description": "the properties to update.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "organizationName": {
                    "type": "string"
                  },
                  "organizationAdmins": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "managedBy": {
                    "type": "string",
                    "description": "User ID of mangager of Organization."
                  },
                  "description": {
                    "type": "string"
                  },
                  "requireContactConsent": {
                    "type": "boolean",
                    "description": "When an organization has this property set to true, anytime a user in the organization sends a message to \na contact who has not yet received a consent message, a consent message will automatically be sent to the contact \n"
                  },
                  "requireContactConsentMessage": {
                    "type": "string",
                    "description": "The body text of the consent message to send.\n"
                  },
                  "billing": {
                    "type": "object",
                    "properties": {
                      "plan": {
                        "type": "string",
                        "description": "The billing plan for users in this organization."
                      }
                    }
                  },
                  "is_disabled": {
                    "type": "boolean",
                    "description": "Marks this organization (and all users belonging to it) as disabled.  This will prevent log-in, sending mesages, \nand blasts / reminders for the afffected users.  Billing (if applicable) will also be suspended for affected users.\n"
                  },
                  "tenantId": {
                    "type": "string",
                    "description": "The ID of the tenant that this organization belongs to.  \nThis is required for new organizations if more than one tenant exists in the instance.\nIf only one tenant exists in the instance, this field will be automatically set to the tenant ID of the only tenant.\nIt is not currently supported to change an organization's tenantId, but this will be added in the future.  \n"
                  },
                  "provider": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/ProviderAccess"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Organization has been updated."
          },
          "400": {
            "description": "There was en error with setting the organization."
          },
          "500": {
            "description": "There was an error updating the billing for a user disable."
          }
        }
      }
    },
    "/api/v2/organizations/{orgid}": {
      "delete": {
        "tags": [
          "apiv2-orgs"
        ],
        "summary": "Delete Organization",
        "description": "Delete organization from provided organization id",
        "parameters": [
          {
            "name": "orgid",
            "in": "path",
            "required": true,
            "description": "The ID of the organization to delete",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "force",
            "in": "query",
            "required": false,
            "description": "When true, the organization is deleted immediately.  Defaults to false, so the org will be deleted after some time.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "delete-users"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "204": {
            "description": "Organization has been removed."
          },
          "400": {
            "description": "There was en error removing the organization."
          },
          "500": {
            "description": "There was an error removing a user from the billing plan."
          }
        }
      }
    },
    "/api/v2/tenants/": {
      "post": {
        "tags": [
          "apiv2-tenants"
        ],
        "summary": "Creates a new Tenant object",
        "security": [
          {
            "SystemToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenantName",
                  "tenant_external_identifier",
                  "provider",
                  "primarySupportContactEmail"
                ],
                "properties": {
                  "tenantName": {
                    "type": "string"
                  },
                  "tenant_external_identifier": {
                    "type": "string",
                    "description": "store an identifer for the tenant for referencing another system"
                  },
                  "billingGroup": {
                    "type": "string",
                    "description": "an identifier used to group multiple tenants for billing purposes"
                  },
                  "adminBillingPlan": {
                    "type": "string",
                    "description": "the internal name of the billing plan assigned to organizations created for Tenant Admins"
                  },
                  "provider": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/ProviderAccess"
                      }
                    ]
                  },
                  "primarySupportContactEmail": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tenant was created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "body": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Created Tenant": {
                    "value": {
                      "body": "Created tenant `tenantName` (`tenantId`)"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Tenant was not created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error message"
                    }
                  }
                },
                "examples": {
                  "General Failure": {
                    "value": {
                      "error": "Failed to create tenant `tenantName`"
                    }
                  },
                  "Malformed Request": {
                    "value": {
                      "error": "Malformed tenant creation request"
                    }
                  },
                  "Already Exists": {
                    "value": {
                      "error": "Tenant creation request failed: Tenant already exists: `tenantName`"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/tenants/createTenantAdmin": {
      "post": {
        "tags": [
          "apiv2-tenants"
        ],
        "summary": "Create Tenant Admin",
        "description": "Creates or updates the tenant admin user (identified by `email`).  \n\nIf a user with the specified email address already exists, the user will be added to the list of administrators \nfor the tenant idenfied by `tenant_external_identifier`\n\nIf this is the first admin created for this tenant, a new organization will be created: \"Tenant Administrators of <tenant name>\" with a billing plan\ndefaulting to either the tenant's `adminBillingPlan`, or the instance's `defaultTenantAdminBillingPlan` value.\n\nThe the tenant to which this admin is being added does not have a support email address, the domain of this request's email address will be used to generate\na support address of `support@<domain>`\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "tenant_external_identifier",
                  "external_id",
                  "full_name"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "Email address of the user to create;  NOT used for correlating the user when consuming SSO claims"
                  },
                  "external_id": {
                    "type": "string",
                    "description": "An identifier used to correlate this user with incoming claims (e.g. SAML NameID) from an external identity provider.  See [SAML Response](#operation/ConsumeSAMLResponse)"
                  },
                  "tenant_external_identifier": {
                    "type": "string",
                    "description": "An identifier used to correlate this tenant with an entity in an external system"
                  },
                  "full_name": {
                    "type": "string",
                    "description": "Name of the user to create/update."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The requested user exists as a tenant admin.  The user may have been updated or created during this request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "body": {
                      "type": "string",
                      "description": "always `User exists as a tenant admin`"
                    },
                    "userId": {
                      "type": "string",
                      "description": "ID of the user"
                    },
                    "tenantId": {
                      "type": "string",
                      "description": "ID of the tenant"
                    },
                    "organizationId": {
                      "type": "string",
                      "description": "ID of the organization for administrators of the selected tenant"
                    },
                    "warning": {
                      "type": "string",
                      "description": "Present only if the tenant's 'supportDetails.primaryContactEmail' value was updated through this request"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request. Possible error scenarios:\n- The request was missing a required property\n- The `tenant_external_identifier` did not match exactly one tenant\n- The user with the specified email address exists, but has a different external_id and belongs to a different tenant.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "description": "A human-readable message providing more details about the error"
                        }
                      }
                    },
                    {
                      "$ref": "#/components/schemas/APIError"
                    },
                    {
                      "$ref": "#/components/schemas/APIErrorTenantAdminAlreadyExists"
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "There was an error creating the tenanat admin"
          }
        }
      }
    },
    "/api/v2/tenants/by-external-id/{id}": {
      "post": {
        "tags": [
          "apiv2-tenants"
        ],
        "summary": "Creates a new or updates a Tenant object",
        "security": [
          {
            "SystemToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenantName",
                  "tenant_external_identifier",
                  "provider",
                  "primarySupportContactEmail"
                ],
                "properties": {
                  "tenantName": {
                    "type": "string"
                  },
                  "tenant_external_identifier": {
                    "type": "string",
                    "description": "store an identifer for the tenant for referencing another system",
                    "note": "changing external_id is not supported for existing tenants"
                  },
                  "billingGroup": {
                    "type": "string",
                    "description": "an identifier used to group multiple tenants for billing purposes"
                  },
                  "adminBillingPlan": {
                    "type": "string",
                    "description": "the internal name of the billing plan assigned to organizations created for Tenant Admins"
                  },
                  "provider": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "The name of the provider"
                      },
                      "credentials": {
                        "type": "object",
                        "description": "an object containing the necessary credentials to authenticate to the provider"
                      }
                    }
                  },
                  "primarySupportContactEmail": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tenant was created or updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "body": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Created Tenant": {
                    "value": {
                      "body": "Created/Updated tenant `tenantName` (`tenantId`)"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Tenant was not created nor updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error message"
                    }
                  }
                },
                "examples": {
                  "General Failure": {
                    "value": {
                      "error": "Failed to create/update tenant `tenantName`"
                    }
                  },
                  "Malformed Request": {
                    "value": {
                      "error": "Malformed tenant creation/update request"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/users/{id}": {
      "get": {
        "tags": [
          "apiv2-users"
        ],
        "summary": "Get User by Id",
        "description": "Retrieves details for a user by ID",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The user's ID"
          }
        ],
        "security": [
          {
            "FirebaseAuth": [
              "admin",
              "teamsadmin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "User GET successful",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicTextableUser"
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Unauthorized to GET User"
          },
          "500": {
            "description": "Failed to GET user"
          }
        }
      },
      "delete": {
        "tags": [
          "apiv2-users"
        ],
        "summary": "Deletes a Private Label User",
        "description": "API Route to delete a user by id.\n\nDefaults to marking the user for deletion insted of actually removing the user.\nSpecify `force` in the query string to forcefully delete the user\n\n`UserToken` authentication for this API call is restricted for retail instances.\n\nSuper Admin users may not be deleted and attempts to do so will fail\n\nAdmin users may be deleted by other admin users\n\nThe user making the request may not delete their own account\n",
        "security": [
          {
            "FirebaseAuth": [
              "admin",
              "teamsadmin"
            ]
          },
          {
            "SystemToken": [
              "delete-users"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the user to delete",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "force",
            "in": "query",
            "required": false,
            "description": "When true, the user is deleted immediately.  Defaults to false, so the user will be deleted after some time.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The user was deleted"
          }
        }
      },
      "patch": {
        "tags": [
          "apiv2-users"
        ],
        "summary": "Update User",
        "description": "Updates properties for a user",
        "security": [
          {
            "FirebaseAuth": [
              "admin",
              "teamsadmin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "requestBody": {
          "description": "User update request body",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "full_name"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "Provide the e-mail address of the user. This is used for login and notifications."
                  },
                  "full_name": {
                    "type": "string",
                    "description": "The full name of the user. e.g. John Doe"
                  },
                  "phone_number": {
                    "type": "string",
                    "description": "The user's phone number in E.164 format.\n\nThe supplied phone number _must not_ be in use by any other users.\n"
                  },
                  "restrictions": {
                    "type": "array",
                    "description": "List of restrictions applied to the user to manage their ability access features.\n\nHere are the matching permission names on Textable UI.\n\n\"blasts\"(Blasts), \"reminders\"(Reminders), \"dripCampaign\"(Drip Campaign), \"importContacts\"(Import Contacts),\n\"lists\"(Contact Lists), \"deleteAll\"(Delete All Contacts), \"disableDelete\"(Delete Contact and Messages), or \"integrations\"(Integrations)\n",
                    "example": [
                      "blasts",
                      "dripCampaign"
                    ],
                    "items": {
                      "type": "string",
                      "enum": [
                        "blasts",
                        "reminders",
                        "dripCampaign",
                        "importContacts",
                        "lists",
                        "deleteAll",
                        "disableDelete",
                        "integrations"
                      ]
                    }
                  },
                  "provider": {
                    "type": "string",
                    "description": "The name of the provider to use for this user\n\nRequired if credentialSource is `user`\n\nIf supplied, all credential properties for the selected provider\nmust be included as top-level keys on the submitted post object\n"
                  },
                  "password": {
                    "type": "string",
                    "description": "Sets the password to the provided value."
                  },
                  "organizationId": {
                    "type": "string",
                    "description": "If not supplied, this will default to the organization of the user making this request\n"
                  },
                  "relayWebhook": {
                    "type": "string",
                    "description": "A publicly available URL that a copy of each message (inbound and outbound) will be sent to via HTTP POST."
                  },
                  "external_id": {
                    "type": "string",
                    "description": "Use this field to store an external_id field for this user (e.g. from your PBX or your identity provider.)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User updated successfully"
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Unauthorized to update User"
          },
          "402": {
            "description": "Unable to update billing for user"
          },
          "409": {
            "description": "Conflict, phone number already in use"
          },
          "500": {
            "description": "Failed to update user"
          }
        }
      }
    },
    "/api/v2/users/": {
      "post": {
        "tags": [
          "apiv2-users"
        ],
        "summary": "Create a Private Label user",
        "description": "Creates a user in the context of a Private Label",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "requestBody": {
          "description": null,
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone_number",
                  "email",
                  "organizationId",
                  "tenantId"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "Provide the e-mail address of the user. This is used for login and notifications."
                  },
                  "full_name": {
                    "type": "string",
                    "description": "The full name of the user. e.g. John Doe"
                  },
                  "isAdmin": {
                    "type": "boolean",
                    "description": "If true, this field sets the user as a system admin. **Note:** This is a sensitive field as it will provide the user access to all organizations and user settings."
                  },
                  "phone_number": {
                    "type": "string",
                    "description": "The user's phone number in E.164 format.\n\nThe supplied phone number _must not_ be in use by any other users.\n"
                  },
                  "restrictions": {
                    "type": "array",
                    "description": "List of restrictions applied to the user to manage their ability access features.\n\nHere are the matching permission names on Textable UI.\n\n\"blasts\"(Blasts), \"reminders\"(Reminders), \"dripCampaign\"(Drip Campaign), \"importContacts\"(Import Contacts),\n\"lists\"(Contact Lists), \"deleteAll\"(Delete All Contacts), \"disableDelete\"(Delete Contact and Messages), or \"integrations\"(Integrations)\n",
                    "example": [
                      "blasts",
                      "dripCampaign"
                    ],
                    "items": {
                      "type": "string",
                      "enum": [
                        "blasts",
                        "reminders",
                        "dripCampaign",
                        "importContacts",
                        "lists",
                        "deleteAll",
                        "disableDelete",
                        "integrations"
                      ]
                    }
                  },
                  "provider": {
                    "type": "string",
                    "description": "The name of the provider to use for this user\n\nRequired if credentialSource is `user`\n\nIf supplied, all credential properties for the selected provider\nmust be included as top-level keys on the submitted post object\n"
                  },
                  "password": {
                    "type": "string",
                    "description": "Sets the password to the provided value."
                  },
                  "organizationId": {
                    "type": "string",
                    "description": "If not supplied, this will default to the organization of the user making this request\n"
                  },
                  "relayWebhook": {
                    "type": "string",
                    "description": "A publicly available URL that a copy of each message (inbound and outbound) will be sent to via HTTP POST."
                  },
                  "external_id": {
                    "type": "string",
                    "description": "Use this field to store an external_id field for this user (e.g. from your PBX or your identity provider.)"
                  },
                  "tenantId": {
                    "type": "string",
                    "description": "The ID of the tenant this user belongs to."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": "object"
                  }
                },
                "examples": {
                  "User Created": {
                    "user": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "402": {
            "description": "Unable to update billing for user"
          },
          "409": {
            "description": "Conflict, phone number already in use"
          },
          "500": {
            "description": "Failed to create user"
          }
        }
      }
    },
    "/api/v2/users/{id}/sendInviteLink": {
      "post": {
        "tags": [
          "apiv2-users"
        ],
        "summary": "Sends welcome email",
        "description": "Sends or resends the welcome email to a new user",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "success"
          },
          "500": {
            "description": "failed to send email"
          }
        }
      }
    },
    "/api/v2/users/{id}/testNotifitactions": {
      "post": {
        "tags": [
          "apiv2-users"
        ],
        "summary": "Sends a test push notification to the user's device(s)",
        "description": "Sends a test push notification to the user's device(s)",
        "responses": {
          "200": {
            "description": "success"
          },
          "500": {
            "description": "failed to send push notification"
          }
        }
      }
    },
    "/api/v2/users/{id}/changePassword": {
      "post": {
        "tags": [
          "apiv2-users"
        ],
        "summary": "Change password",
        "description": "Changes the password of the user specified in :id. All other logged-in sessions of this user will be terminated. If the requestor is changing their own password, a new auth token will be returned.",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "requestBody": {
          "description": "New password",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "password": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Password has been reset",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "value": "Reset password"
                    },
                    "newToken": {
                      "description": "The new auth token used to re-authenticate the user",
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "Reset Own Password": {
                    "value": {
                      "status": "Reset own password",
                      "newToken": "#NEW TOKEN"
                    }
                  },
                  "Reset Another User's  Password": {
                    "value": {
                      "status": "Reset password"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Unauthorized to reset password"
          },
          "500": {
            "description": "Failed to reset password"
          }
        }
      }
    },
    "/api/v2/users/{id}/token": {
      "post": {
        "tags": [
          "apiv2-users"
        ],
        "summary": "Create user API Token",
        "description": "Create user API Token",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The newly created token",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "The newly created user API token"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Failed"
          }
        }
      }
    },
    "/api/v2/users/{id}/token/{tokenId}": {
      "delete": {
        "tags": [
          "apiv2-users"
        ],
        "summary": "Delete user API Token",
        "description": "Delete user API Token",
        "security": [
          {
            "FirebaseAuth": [
              "admin"
            ]
          },
          {
            "SystemToken": [
              "edit-users"
            ]
          },
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The token was deleted"
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Failed"
          }
        }
      }
    },
    "/api/v2/users/generate-jwt": {
      "post": {
        "summary": "Generate a JWT token for a user",
        "description": "Generates a JWT token for a user with the given user ID.",
        "tags": [
          "Service Accounts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userId": {
                    "type": "string",
                    "description": "The ID of the user for whom to generate the JWT."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully generated JWT token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "The generated JWT token."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Failed to generate JWT token."
          }
        }
      }
    },
    "/api/v2/users/revoke-user-token/by-external-id": {
      "post": {
        "summary": "Revoke user token by external ID",
        "description": "Revokes a user's token using their external ID.",
        "tags": [
          "Service Accounts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "description": "The external ID of the user whose token is to be revoked."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully revoked user token."
          },
          "500": {
            "description": "Failed to revoke user token."
          }
        }
      }
    },
    "/api/v2/users/revoke-user-token/by-email": {
      "post": {
        "summary": "Revoke user token by email",
        "description": "Revokes a user's token using their email address.",
        "tags": [
          "Service Accounts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "The email of the user whose token is to be revoked."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully revoked user token."
          },
          "500": {
            "description": "Failed to revoke user token."
          }
        }
      }
    },
    "/api/v2/users/revoke-user-token/by-uid": {
      "post": {
        "summary": "Revoke user token by UID",
        "description": "Revokes a user's token using their UID.",
        "tags": [
          "Service Accounts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userId": {
                    "type": "string",
                    "description": "The UID of the user whose token is to be revoked."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully revoked user token."
          },
          "500": {
            "description": "Failed to revoke user token."
          }
        }
      }
    },
    "/api/contacts": {
      "get": {
        "tags": [
          "apiv1-contacts"
        ],
        "summary": "Get list of contacts.",
        "description": "Lists contacts owned by the user associated with the API key used to make the request",
        "security": [
          {
            "UserToken": []
          }
        ],
        "responses": {
          "200": {
            "description": null,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "abc123xyz"
                          },
                          "phoneNumber": {
                            "type": "string",
                            "example": "+15554443333"
                          },
                          "fullName": {
                            "type": "string",
                            "example": "John Doe",
                            "description": "Full name of contact. (e.g. John Doe)"
                          },
                          "email": {
                            "type": "string",
                            "description": "E-mail address of contact.",
                            "example": "john.doe@gmail.com"
                          },
                          "last_message": {
                            "type": "string",
                            "example": "Hello, Textable!",
                            "description": "The last message that was sent or received for this contact."
                          },
                          "last_message_date": {
                            "type": "number",
                            "example": 1670372913091,
                            "description": "A UTC timestamp (in milliseconds) of the last message sent or received."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "apiv1-contacts"
        ],
        "summary": "Create a contact.",
        "description": null,
        "security": [
          {
            "UserToken": []
          }
        ],
        "requestBody": {
          "description": "Create a contact.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phoneNumber"
                ],
                "properties": {
                  "phoneNumber": {
                    "type": "string",
                    "description": "The contact's phone number in E.164 format",
                    "example": "+15554443333"
                  },
                  "fullName": {
                    "type": "string",
                    "description": "Full name of contact.",
                    "example": "John Doe"
                  },
                  "email": {
                    "type": "string",
                    "description": "E-mail address of contact.",
                    "example": "john.doe@gmail.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": null,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "abc123xyz"
                    },
                    "fullName": {
                      "type": "string",
                      "example": "John Doe",
                      "description": "Full name of contact. (e.g. John Doe)"
                    },
                    "email": {
                      "type": "string",
                      "description": "E-mail address of contact.",
                      "example": "john.doe@gmail.com"
                    },
                    "last_message": {
                      "type": "string",
                      "example": "Hello, Textable!",
                      "description": "The last message that was sent or received for this contact."
                    },
                    "last_message_date": {
                      "type": "number",
                      "example": 1670372913091,
                      "description": "A UTC timestamp (in milliseconds) of the last message sent or received."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/contacts/{id}": {
      "get": {
        "tags": [
          "apiv1-contacts"
        ],
        "summary": "Get a single contact by id.",
        "description": null,
        "security": [
          {
            "UserToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Contact document id"
          }
        ],
        "responses": {
          "200": {
            "description": "Contact response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "abc123xyz"
                    },
                    "fullName": {
                      "type": "string",
                      "example": "John Doe",
                      "description": "Full name of contact. (e.g. John Doe)"
                    },
                    "email": {
                      "type": "string",
                      "description": "E-mail address of contact.",
                      "example": "john.doe@gmail.com"
                    },
                    "last_message": {
                      "type": "string",
                      "example": "Hello, Textable!",
                      "description": "The last message that was sent or received for this contact."
                    },
                    "last_message_date": {
                      "type": "number",
                      "example": 1670372913091,
                      "description": "A UTC timestamp (in milliseconds) of the last message sent"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/contacts/{id}/drip": {
      "post": {
        "summary": "Apply a drip campaign to a contact",
        "description": "Applies a drip campaign to a specific contact if the authenticated user has access to both the contact and the campaign.",
        "tags": [
          "apiv1-contacts"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The ID of the contact"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "dripCampaignId": {
                    "type": "string",
                    "description": "ID of the drip campaign to apply"
                  }
                },
                "required": [
                  "dripCampaignId"
                ]
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Drip campaign successfully applied"
          },
          "400": {
            "description": "Invalid request (e.g. unauthorized, invalid contact or campaign ID)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "UserToken": []
          }
        ]
      }
    },
    "/api/drips": {
      "get": {
        "tags": [
          "apiv1-drips"
        ],
        "summary": "Get list of drip campaigns for the current user.",
        "description": null,
        "security": [
          {
            "UserToken": []
          }
        ],
        "responses": {
          "200": {
            "description": null,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "drips": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "abc123xyz"
                          },
                          "name": {
                            "type": "string",
                            "example": null,
                            "description": "(Deprecated, likely to be null)"
                          },
                          "drips": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string",
                                  "example": null,
                                  "description": "(Deprecated, likely to be null)"
                                },
                                "interval": {
                                  "type": "number",
                                  "example": 1,
                                  "description": "The number of units to apply the drip campaign (based on intervalType. e.g. 5 days)"
                                },
                                "intervalType": {
                                  "type": "string",
                                  "enum": [
                                    "minutes",
                                    "hours",
                                    "days"
                                  ],
                                  "example": "days",
                                  "description": "The type of interval to apply the drip campaign (based on the interval. e.g. 5 days)"
                                },
                                "message": {
                                  "type": "string",
                                  "example": "Hello, [first]! Thanks for stopping by our booth at the event. I'd love to connect this week about your needs. Let me know when you're available!",
                                  "description": "The body of the message that you would like to be sent."
                                },
                                "created": {
                                  "type": "string",
                                  "example": null,
                                  "description": "(Deprecated, likely to be null)"
                                }
                              }
                            }
                          },
                          "created": {
                            "type": "number",
                            "example": null,
                            "description": "(Deprecated, likely to be null)"
                          },
                          "updated": {
                            "type": "string",
                            "example": null,
                            "description": "(Deprecated, likely to be null)"
                          },
                          "uid": {
                            "type": "string",
                            "example": "abc123xyz",
                            "description": "The user id that the canned response belongs to."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/canned-responses": {
      "get": {
        "tags": [
          "apiv1-canned"
        ],
        "summary": "Get list of canned responses for a user.",
        "description": null,
        "security": [
          {
            "UserToken": []
          }
        ],
        "requestBody": null,
        "responses": {
          "200": {
            "description": null,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "canned": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "example": "abc123xyz"
                          },
                          "auto_keyword": {
                            "type": "string",
                            "example": "HELLO",
                            "description": "(Optional) If set, the app will automatically reply when this keyword is received."
                          },
                          "body": {
                            "type": "string",
                            "example": "Hello, world! Thanks for contacting us!",
                            "description": "The body of the canned response that will be copied into a new message or used as an auto-reply."
                          },
                          "name": {
                            "type": "string",
                            "example": "HELLO Auto-Reply",
                            "description": "A display name for the canned response."
                          },
                          "uid": {
                            "type": "string",
                            "example": "abc123xyz",
                            "description": "The user id that the canned response belongs to."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/send": {
      "post": {
        "tags": [
          "apiv1-messages"
        ],
        "summary": "Send (or schedule) a SMS or MMS message",
        "description": "Send (or schedule) a SMS or MMS message for a specified phone number, store a \"note\" or a message sent from an external system.",
        "security": [
          {
            "UserToken": []
          }
        ],
        "requestBody": {
          "description": "Send, schedule or store a SMS / MMS message or store a note.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "to",
                  "from",
                  "message"
                ],
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "The recipient's phone number in E.164 format.",
                    "example": "+15554443333"
                  },
                  "from": {
                    "type": "string",
                    "description": "The sender's phone number in E.164 format.",
                    "example": "+15554442222"
                  },
                  "message": {
                    "type": "string",
                    "description": "The body of the message.",
                    "example": "Hello, Textable!"
                  },
                  "media": {
                    "type": "array",
                    "description": "(Optional) An array of publicly available URLs to include as MMS attachments.",
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "https://cdn.mycdn.com/assets/my/mms/file.jpg"
                    ]
                  },
                  "notify": {
                    "type": "boolean",
                    "description": "(Optional) A boolean that dictates whether or not to send a notification to the Texatble user that a note or message has been stored.",
                    "example": true
                  },
                  "sendAt": {
                    "type": "number",
                    "description": "(Optional) A UTC timestamp in the future when to schedule the message to be sent. The timestamp is in ms.",
                    "example": 2880544055000
                  },
                  "sendStatus": {
                    "type": "string",
                    "enum": [
                      "sent"
                    ],
                    "description": "(Optional) If set to \"sent\", this will store a message, not send it, assuming it has already been sent to the carrier.",
                    "example": "sent"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "note"
                    ],
                    "description": "(Optional) If set to \"note\", this will store the message body as a note that is visible to all users and shared users of the from number. This will NOT send a message to the recipient.",
                    "example": "note"
                  },
                  "autoArchive": {
                    "type": "boolean",
                    "default": false,
                    "description": "If true, the conversation's archived status will be set to true."
                  },
                  "reminder": {
                    "type": "boolean",
                    "description": "If true, the message will be a reminder and displayed in the reminder section in the app. **note reminder messages require timezone and sendAt fields"
                  },
                  "scheduleTimezone": {
                    "type": "string",
                    "enum": [
                      "America/Los_Angeles",
                      "America/Denver",
                      "America/Chicago",
                      "America/New_York"
                    ],
                    "description": "A required field for sending reminders.",
                    "example": "America/Los_Angeles"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message Sent/Scheduled"
          },
          "400": {
            "description": "Error sending message due to bad request"
          },
          "404": {
            "description": "An error with the user or contact prevented sending the messasge"
          },
          "451": {
            "description": "An error sending a message due to legal demands (user opted out)"
          },
          "500": {
            "description": "The message failed to send"
          }
        }
      }
    },
    "/api/export": {
      "get": {
        "tags": [
          "apiv1-other"
        ],
        "summary": "Get an export",
        "description": null,
        "security": [
          {
            "UserToken": []
          }
        ],
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/api/organizations": {
      "get": {
        "tags": [
          "apiv1-orgs"
        ],
        "summary": "Get list of organizations.",
        "description": null,
        "security": [
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": null,
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "example": "iw8guE9ndCkMXzyVmDezmyO0Il0SzA9i"
                      },
                      "organizationName": {
                        "type": "string",
                        "example": "Right Way Insurance Co."
                      },
                      "description": {
                        "type": "string"
                      },
                      "userCount": {
                        "type": "number"
                      },
                      "managedBy": {
                        "type": "string",
                        "example": "iw8guE9ndCkMXzyVmDezmyO0Il0SzA9i"
                      },
                      "billing": {
                        "type": "object",
                        "properties": {
                          "plan": {
                            "type": "string",
                            "example": "starter"
                          }
                        }
                      },
                      "organizationAdmins": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "example": [
                          "abc123xyz"
                        ]
                      },
                      "requireContactConsent": {
                        "type": "boolean"
                      },
                      "requireContactConsentMessage": {
                        "type": "string",
                        "example": "This is an example consent message. Reply STOP to opt out."
                      },
                      "is_disabled": {
                        "type": "boolean"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "apiv1-orgs"
        ],
        "summary": "Creates an organization.",
        "description": null,
        "security": [
          {
            "UserToken": []
          }
        ],
        "requestBody": {
          "description": null,
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "organizationName"
                ],
                "properties": {
                  "organizationName": {
                    "type": "string",
                    "description": "A short name for the organization."
                  },
                  "description": {
                    "type": "string",
                    "description": "Description or note for the organization."
                  },
                  "organizationPlanSelection": {
                    "type": "string",
                    "description": "A string representing the plan name of the organization.",
                    "example": "mcpl-starter"
                  },
                  "billing": {
                    "type": "object",
                    "properties": {
                      "plan": {
                        "type": "string",
                        "example": "mcpl-starter"
                      }
                    }
                  },
                  "requireContactConsent": {
                    "type": "boolean",
                    "description": "A boolean value representing whether or not the organization should enforce sending the consent message."
                  },
                  "requireContactConsentMessage": {
                    "type": "string",
                    "description": "A string representing the content of the organization's consent message."
                  },
                  "tenantId": {
                    "type": "string",
                    "description": "The ID of the tenant that this organization belongs to.  \nThis is required for new organizations if more than one tenant exists in the instance.\nIf only one tenant exists in the instance, this field will be automatically set to the tenant ID of the only tenant.\nIt is not currently supported to change an organization's tenantId, but this will be added in the future.  \n"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Organization has been created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "iw8guE9ndCkMXzyVmDezmyO0Il0SzA9i",
                      "description": "The id of the newly created organization."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "There was an error with creating the organization.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A description of the error that occurred."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "There was a server error when creating the organization.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A description of the error that occurred."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/organizations/:id": {
      "post": {
        "tags": [
          "apiv1-orgs"
        ],
        "summary": "Update an organization.",
        "description": null,
        "security": [
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "requestBody": {
          "description": null,
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "organizationName"
                ],
                "properties": {
                  "organizationName": {
                    "type": "string",
                    "description": "A short name for the organization."
                  },
                  "description": {
                    "type": "string",
                    "description": "Description or note for the organization."
                  },
                  "organizationPlanSelection": {
                    "type": "string",
                    "description": "A string representing the plan name of the organization.",
                    "example": "mcpl-starter"
                  },
                  "billing": {
                    "type": "object",
                    "properties": {
                      "plan": {
                        "type": "string",
                        "example": "mcpl-starter"
                      }
                    }
                  },
                  "requireContactConsent": {
                    "type": "boolean",
                    "description": "A boolean value representing whether or not the organization should enforce sending the consent message."
                  },
                  "requireContactConsentMessage": {
                    "type": "string",
                    "description": "A string representing the content of the organization's consent message."
                  },
                  "is_disabled": {
                    "type": "boolean",
                    "description": "Marks this organization (and all users belonging to it) as disabled. This will prevent log-in, sending mesages, and blasts / reminders for the afffected users. Billing (if applicable) will also be suspended for affected users."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The organization has been updated."
          },
          "400": {
            "description": "There was an error with updating the organization."
          },
          "500": {
            "description": "There was an error updating the organization."
          }
        }
      }
    },
    "/api/organizations/{id}/admin": {
      "post": {
        "tags": [
          "apiv1-orgs"
        ],
        "summary": "Add Organization Admin",
        "description": "Adds an organization admin to organization referenced by \"id\", based on e-mail address",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the organization to edit",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "email address of the user to add",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "The email address of the user to add as an org admin\n\nMust already exist as a user in the application\n"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "204": {
            "description": "Organization admin has been added."
          },
          "400": {
            "description": "There was en error adding the organization admin."
          }
        }
      }
    },
    "/api/organizations/{orgid}/admin/{userid}": {
      "delete": {
        "tags": [
          "apiv1-orgs"
        ],
        "summary": "Delete Organization Admin",
        "description": "Delete organization admin from provided organization id",
        "parameters": [
          {
            "name": "orgid",
            "in": "path",
            "required": true,
            "description": "The ID of the organization to edit",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userid",
            "in": "path",
            "required": true,
            "description": "The user id of the admin to remove from the org",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "204": {
            "description": "Organization admin has been removed."
          },
          "400": {
            "description": "There was en error removing the organization admin."
          }
        }
      }
    },
    "/api/users": {
      "get": {
        "tags": [
          "apiv1-users"
        ],
        "summary": "Gets users",
        "description": "Gets all users in the application.  Requires admin since no users are trimmed from the result set.",
        "security": [
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Array of user objects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string"
                      },
                      "full_name": {
                        "type": "string"
                      },
                      "firebase_document_id": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "apiv1-users"
        ],
        "summary": "Create user",
        "description": "Creates a user.   \n\nOnly valid in `privatelabel` context.\n\nNewly created users must have a email and phone number that are not already in use.\n",
        "security": [
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "requestBody": {
          "description": "Details about the user to create",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phoneNumber",
                  "emailAddress"
                ],
                "properties": {
                  "phoneNumber": {
                    "type": "string",
                    "description": "The user's phone number in E.164 format.\n\nThe supplied phone number _must not_ be in use by any other users.\n"
                  },
                  "provider": {
                    "type": "string",
                    "description": "The name of the provider to use for this user\n\nRequired if credentialSource is `user`\n\nIf supplied, all credential properties for the selected provider\nmust be included as top-level keys on the submitted post object\n"
                  },
                  "emailAddress": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  },
                  "fullName": {
                    "type": "string"
                  },
                  "organizationId": {
                    "type": "string",
                    "description": "If not supplied, this will default to the organization of the user making this request\n"
                  },
                  "relayWebhook": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ID of the created user",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/users/{id}": {
      "post": {
        "tags": [
          "apiv1-users"
        ],
        "summary": "Edit user",
        "description": "Updates a user's details.\n\nNotice: it is not possible to update certain user fields via this API:\n  *  Provider Credentials\n  *  Application password\n",
        "security": [
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the user to edit",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Details about the user to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phoneNumber": {
                    "type": "string",
                    "description": "The user's phone number in E.164 format.\n\nThe supplied phone number _must not_ be in use by any other users.\n"
                  },
                  "emailAddress": {
                    "type": "string",
                    "description": "If the email supplied is different from the users existing email, \nit will be updated in the authentication system and the existing password will continue to work\n"
                  },
                  "provider": {
                    "type": "string",
                    "description": "The name of the provider to use for this user"
                  },
                  "fullName": {
                    "type": "string"
                  },
                  "organizationId": {
                    "type": "string"
                  },
                  "relayWebhook": {
                    "type": "string"
                  },
                  "disabled": {
                    "type": "boolean",
                    "description": "Users marked as disabled may not log in or make API calls.  \nCanned resposnes or auto replies for these users will not be sent.\nIf applicable, the billing quantity will also be reduced for disabled users.\n"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The update was successful.  No content is returned."
          }
        }
      }
    },
    "/api/users/{id}/webhook": {
      "post": {
        "tags": [
          "apiv1-users"
        ],
        "summary": "Edit user Webhook URL",
        "description": "Updates the webhook URL for a user",
        "security": [
          {
            "UserToken": [
              "self"
            ]
          }
        ],
        "requestBody": {
          "description": "Update detail for the webhook URL",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "URL to which messages (inbound and outbound) should be POSTed\n\nFormat of the POST body will be:\n```\n{\n   MessageID: string\n   ConversationID: string\n   ToNumber: string\n   FromNumber: string\n   MessageBody: string\n   MessageDirection: string\n   TextableUserID: string\n   ContactName: string\n   ContactEmail: string\n   AccessToken?: string  \n}\n```\n"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/api/users/{id}/token": {
      "post": {
        "tags": [
          "apiv1-users"
        ],
        "summary": "Create user API Token",
        "description": "Create a user API token",
        "security": [
          {
            "UserToken": [
              "admin"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The newly created token",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "The newly created user API token"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/providers": {
      "get": {
        "tags": [
          "SSO"
        ],
        "summary": "Gets available SSO providers",
        "description": "Gets a list of the configured Identity Providers (IdP) for this instance from Firestore.  \n\nThese providers are currently maintained by manually editing documents in the `auth-providers` collection\nbut TXBDEV-1102 will create an in-app management page for IdP\n",
        "security": [],
        "responses": {
          "200": {
            "description": "a list of auth providers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string"
                      },
                      "backendURL": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "color": {
                        "type": "string"
                      },
                      "showLoginButton": {
                        "type": "boolean"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/password-login-allowed/{email}": {
      "get": {
        "tags": [
          "SSO"
        ],
        "summary": "Check if password login is allowed for a user",
        "description": "Determines whether password login is permitted for the specified e-mail address, based on the user record\nand system-wide settings. If the user has an external SSO ID, password login is only allowed if the feature\n'restrictLocalPasswordLogin' is disabled in app-data/authentication. This same logic is applied for determining\nself-service passwrod reset eligibility\n",
        "parameters": [
          {
            "in": "path",
            "name": "email",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The e-mail address to check"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns whether password login is allowed for the provided email",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "passwordLoginAllowed": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input or missing email"
          },
          "500": {
            "description": "Internal server error"
          }
        }
      }
    },
    "/auth/oauth/:provider/login": {
      "get": {
        "operationId": "StartOAuthSSO",
        "tags": [
          "SSO"
        ],
        "summary": "Start OAuth SSO Workflow",
        "description": "Called by frontend or mobile AuthNZ service's `providerLogin` function to initiate the SSO workflow for an OAuth Authorization Server\n\nWill almost always be loaded within the scope of a browser popup or mobile InAppBrowser (having location bar and cache disabled)\n\nExpected flow is defined in RFC 6749, section 4.1: [Authorization Code Grant](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1)\n\nThe response from the Authorization Server should result in a [GET call to](#operation/ConsumeOAuthResponse) `/auth/oauth/:provider/callback` \n",
        "parameters": [
          {
            "in": "path",
            "name": "provider",
            "description": "The ID of the provider for which to start the SSO workflow.\n",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "responses": {
          "302": {
            "description": "Redirects to the Authoirzation Server with the goal of obtaining a \"code\" which can be exchanged for an access token",
            "headers": {
              "Location": {
                "description": "The Authoirzation Server's `authorizationURL`",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong while trying to redirect the user to the  Authoirzation Server's login page",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string",
                  "description": "plain text error and possibly a stack trace"
                }
              }
            }
          }
        }
      }
    },
    "/auth/oauth/:provider/callback": {
      "post": {
        "operationId": "ConsumeOAuthResponse",
        "tags": [
          "SSO"
        ],
        "summary": "Receive OAuth \"Authorization Grant\" code",
        "description": "Process the \"Authorization Grant\" code response from the Authorization Server.\n\nExchang the \"code\" for an \"Access Token\" and optionally fetch the UserInfo for the user\n\nCorrelate incoming claims with a user in our database, and issues a signing token for frontend / mobile.\nIf no user exists and \"allowJITProvisioning\" is enabled, a new user is created and a signing token is issued.\nIf no user exists and \"allowJITProvisioning\" is disabled, an error is returned\n",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "OAuth \"Authorization Grant\" code returned by the Authorization Server to be exchanged for an \"Access Token\""
          },
          {
            "name": "refresh_token",
            "in": "query",
            "deprecated": true,
            "schema": {
              "type": "string"
            },
            "description": "For OAuth2 Authorization Servers that deviate from [RFC6749 4.1.2](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2), this parameter can be used in place of the \"code\" parameter"
          }
        ],
        "responses": {
          "200": {
            "description": "The claims were successfully processed and associated with a user",
            "content": {
              "text/html": {
                "schema": {
                  "description": "A very simple HTML page which displays the text `REDIRECTING` and defines a JavaScript function `SAMLPostback()`.  \n\nThis page should generally not be visible to the user for more than a few hundered milliseconds.\n\nOn desktop browsers, this function uses `window.postMessage` to send the `ssoResponse` object back to the window responsible for opening the SSO popup\n\nIn the mobile app, this function returns the value of `ssoResponse` to the InAppBrowser's `browser.executeScript` call\n",
                  "type": "string"
                },
                "examples": {
                  "Function Page": {
                    "value": "<html><body><script>\n  function SAMLPostback() {\n  const ssoResponse={\"token\":\"\",\"error\":true};\n  if (window.webkit && window.webkit.messageHandlers) {\n  return ssoResponse;\n  } else { \n  opener.postMessage(ssoResponse,'undefined');\n  }\n  window.close();\n  }\n  SAMLPostback();\n</script>REDIRECTING</body></html>\n"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/saml/login": {
      "get": {
        "operationId": "CreateSAMLRequest",
        "tags": [
          "SSO"
        ],
        "summary": "Start SAML SSO Workflow",
        "description": "Called by frontend or mobile AuthNZ service's `providerLogin` function to initiate the SSO workflow for an Identity Provider (IdP)\n\nWill almost always be laoded within the scope of a browser popup or mobile InAppBrowser (having location bar and cache disabled)\n\nThe response of a successful authentication from the IdP [will be posted to](#operation/ConsumeSAMLResponse) `/auth/saml/callback`\n",
        "parameters": [
          {
            "in": "path",
            "name": "ProviderName",
            "description": "The name of the provider for which to start the SSO workflow.  Must match the `name` of the document in `auth-providers`.\n\nUsed in `getAuthProviderNameFromRequest` to resolve to a Firebase document\n",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "responses": {
          "302": {
            "description": "Redirects to the IdP with the goal of obtaining user identity claims in a `SAMLResponse`",
            "headers": {
              "Location": {
                "description": "The IdP's `LoginURL`, with a base64 encoded `SAMLRequest` XML docuemnt and a URL encoded `RelayState` JSON opject as URL parameters",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong while trying to redirect the user to the IdP login page; likely the `ProviderName` parameter was unknown or not supplied",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string",
                  "description": "plain text error and possibly a stack trace"
                }
              }
            }
          }
        }
      }
    },
    "/auth/saml/callback": {
      "post": {
        "operationId": "ConsumeSAMLResponse",
        "tags": [
          "SSO"
        ],
        "summary": "Consume SAMLResponse body from IdP",
        "description": "Receive and process the SAML response given to us by the IdP.  \n\nVerify issuer of incoming claims by ensuring the signature can be verified by the IdP's certificate, and that the \nincoming claims were the result of a request we actually made (i.e. not requested by another party).\n\n Correlate incoming claims with a user in our database, and issues a signing token for frontend / mobile       \n",
        "requestBody": {
          "description": "Claims provided by the IdP in response to a successful authentication",
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "RelayState": {
                    "type": "object",
                    "description": "JSON object which was [created by](#operation/CreateSAMLRequest) `/auth/saml/login`; passed to the IdP; and then passed back to this endpoint"
                  },
                  "SAMLResponse": {
                    "type": "string",
                    "description": "Base64 encoded XML document conatining a SAMLResponse"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The claims were successfully processed and associated with a user",
            "content": {
              "text/html": {
                "schema": {
                  "description": "A very simple HTML page which displays the text `REDIRECTING` and defines a JavaScript function `SAMLPostback()`.  \n\nThis page should generally not be visible to the user for more than a few hundered milliseconds.\n\nOn desktop browsers, this function uses `window.postMessage` to send the `ssoResponse` object back to the window responsible for opening the SSO popup\n\nIn the mobile app, this function returns the value of `ssoResponse` to the InAppBrowser's `browser.executeScript` call\n",
                  "type": "string"
                },
                "examples": {
                  "Function Page": {
                    "value": "<html><body><script>\n  function SAMLPostback() {\n  const ssoResponse={\"token\":\"\",\"error\":true};\n  if (window.webkit && window.webkit.messageHandlers) {\n  return ssoResponse;\n  } else { \n  opener.postMessage(ssoResponse,'undefined');\n  }\n  window.close();\n  }\n  SAMLPostback();\n</script>REDIRECTING</body></html>\n"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/frontend/biling/tenantReport/:tenantId": {
      "get": {
        "tags": [
          "frontend"
        ],
        "summary": "Get Billing For a Tenant",
        "description": "Gets billing details for a single tenant",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/frontend/biling/tenantReport/{tenantId}": {
      "get": {
        "tags": [
          "frontend"
        ],
        "summary": "Get Billing For all Tenants",
        "description": "Gets billing details for all tenants",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/frontend/integrations/isntalled": {
      "post": {
        "tags": [
          "frontend"
        ],
        "summary": "Get Installed integrations",
        "description": "Gets integrations currently installed for the requesting user.",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/frontend/integrations/available": {
      "post": {
        "tags": [
          "frontend"
        ],
        "summary": "Get Available integrations",
        "description": "Gets integrations available for installation by the requesting user.",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/frontend/oragnizations": {
      "post": {
        "tags": [
          "frontend"
        ],
        "summary": "Adds an organization",
        "description": "Adds an organization for either private label or retail",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/frontend/oragnizations/{id}": {
      "post": {
        "tags": [
          "frontend"
        ],
        "summary": "Adds an organization",
        "description": "Adds an organization for either private label or retail",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/frontend/users/{id}/shared": {
      "get": {
        "tags": [
          "frontend"
        ],
        "summary": "Updates number sharing for a user",
        "description": "Updates number sharing for a user",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/frontend/editUserMessageSettings": {
      "post": {
        "tags": [
          "frontend"
        ],
        "summary": "Updates the User's message settings",
        "description": "API endpoint for use only by PrivateFrontend (the web application). Allows the \"Messaging Settings\" page to change User Documents",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": null
          }
        }
      }
    },
    "/health": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Healthcheck",
        "description": "Returns 200 if the backend application is behaving correctly",
        "responses": {
          "200": {
            "description": "Service is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/definitions/HealthCheckResponse"
                }
              }
            }
          },
          "503": {
            "description": "Service is unhealthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/definitions/HealthCheckResponse"
                }
              }
            }
          }
        }
      }
    },
    "/deleteConversation": {
      "post": {
        "tags": [
          "frontend"
        ],
        "summary": "Delete conversation history",
        "description": "Deletes all messages in a conversation, sets the last message to null, and marks the conversation as read and archived",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "contact_id"
                ],
                "properties": {
                  "contact_id": {
                    "type": "string",
                    "description": "The rcontact id to delete messages for"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "success"
          },
          "404": {
            "description": "contact with provided contactId does not exist"
          },
          "500": {
            "description": "unexpected error"
          }
        }
      }
    },
    "/getContactConsentRequirement": {
      "get": {
        "tags": [
          "frontend"
        ],
        "summary": "Get Contact Consent Requirement",
        "description": "Determines whether the requested contact is subject to required consent-obtaining messages.",
        "security": [
          {
            "FirebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "success"
          },
          "400": {
            "description": "undefined query string"
          },
          "404": {
            "description": "contact with provided contactId does not exist"
          },
          "500": {
            "description": "contacts document .get() failure"
          }
        }
      }
    },
    "/receive?provider=": {
      "get": {
        "summary": "Receive an event from a telco provider",
        "description": "Handles all incoming events (messages, DLRs, etc) from telco providers.",
        "tags": null,
        "security": null,
        "parameters": [
          {
            "name": "provider",
            "in": "query",
            "required": true,
            "description": "The name of the provider; dictates the schema / method for processing the request body\n",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Message was received (and possibly stored for a known user )",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string",
                  "enum": [
                    ""
                  ],
                  "description": "DEPRECATED.  The message was received, but not necessarily stored"
                }
              },
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "resultText": {
                      "type": "string",
                      "enum": [
                        "Message stored for unknown user",
                        "Message stored for known user"
                      ]
                    },
                    "resultData": {
                      "type": "object",
                      "required": [],
                      "properties": {
                        "messageId": {
                          "type": "string",
                          "description": "The ID of the message object that was stored in the database"
                        },
                        "userId": {
                          "type": "string",
                          "description": "The ID of the user object for whom the message was stored"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "There was a problem with the request;\nusually because the payload format was incorrect, or\nthe URL query string did not include a known provider attribtue\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Must specify provider",
                        "Unable to parse event",
                        "Unknown provider requested"
                      ],
                      "description": "A message indicating the specific error"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "There was an error storing the message.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "resultText": {
                      "type": "string",
                      "enum": [
                        "Message not stored for unknown user",
                        "Unable to find or create a contact for user; message not stored",
                        "Message not stored"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "definitions": {
    "HealthCheckComponent": {
      "type": "object",
      "properties": {
        "componentId": {
          "type": "string",
          "description": "Unique identifier of an instance of a specific sub-component"
        },
        "componentType": {
          "type": "string",
          "description": "Type of the component"
        },
        "observedValue": {
          "description": "Observed value - can be any valid JSON value"
        },
        "observedUnit": {
          "type": "string",
          "description": "Unit of measurement for observedValue"
        },
        "status": {
          "type": "string",
          "enum": [
            "pass",
            "fail",
            "warn",
            "ok",
            "error",
            "up",
            "down"
          ],
          "description": "Health status of this component"
        },
        "affectedEndpoints": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "URI Templates for affected endpoints"
        },
        "time": {
          "type": "string",
          "format": "date-time",
          "description": "ISO8601 timestamp when the value was recorded"
        },
        "output": {
          "type": "string",
          "description": "Raw error output for fail/warn states"
        },
        "links": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "description": "Related links"
        }
      },
      "additionalProperties": true
    },
    "HealthCheckResponse": {
      "type": "object",
      "required": [
        "status",
        "time"
      ],
      "properties": {
        "status": {
          "type": "string",
          "enum": [
            "pass",
            "fail",
            "warn",
            "ok",
            "error",
            "up",
            "down"
          ],
          "description": "Health status"
        },
        "time": {
          "type": "string",
          "format": "date-time",
          "description": "ISO8601 timestamp when the response was generated"
        },
        "version": {
          "type": "string",
          "description": "Public version of the service"
        },
        "releaseId": {
          "type": "string",
          "description": "Release identifier"
        },
        "notes": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Notes relevant to current state"
        },
        "output": {
          "type": "string",
          "description": "Raw error output (omit for \"pass\" state)"
        },
        "checks": {
          "type": "object",
          "additionalProperties": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/HealthCheckComponent"
            }
          },
          "description": "Detailed health statuses of downstream systems"
        },
        "links": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "description": "Link relations and URIs"
        },
        "serviceId": {
          "type": "string",
          "description": "Unique identifier of the service"
        },
        "description": {
          "type": "string",
          "description": "Human-friendly description"
        }
      }
    },
    "TenantBillingObject": {
      "type": "object",
      "properties": {
        "TenantName": {
          "type": "string",
          "example": "Skyswitch Training"
        },
        "TenantExternalId": {
          "type": "number",
          "description": "The external id of the tenant.",
          "example": 20681
        },
        "TenantBillingGroup": {
          "type": "string",
          "description": "The identifier used to group multiple tenants for billing purposes"
        },
        "LicenseAllocation": {
          "type": "object",
          "example": {
            "cloudmessage-pro": 10
          }
        },
        "OrganizationBreakdown": {
          "type": "array",
          "example": [
            {
              "organizationName": "Tenant Administrators of Skyswitch Training",
              "users": [
                {
                  "id": "1WDp8ArAXWYH24C5mqXskl6SXGf2",
                  "email": "michael.mcintosh+20681@skyswitch.com",
                  "externalId": "michael.mcintosh+20681@skyswitch.com"
                }
              ],
              "LicenseType": "cloudmessage-dashmanger",
              "LicenseQuantity": 10,
              "UserQuantity": 10
            }
          ],
          "items": {
            "type": "object",
            "properties": {
              "organizationName": {
                "type": "string",
                "description": "The name of the organization.",
                "example": "Skyswitch Training"
              },
              "externalId": {
                "type": "string",
                "description": "The external id of the organization.",
                "example": "Skyswitch Training"
              },
              "users": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "example": "O2r4OQEKE4WTUhCT3wQcUz2xtJm1"
                    },
                    "email": {
                      "type": "string",
                      "example": "john.doe@gmail.com"
                    },
                    "externalId": {
                      "type": "string",
                      "example": "user@domain"
                    }
                  }
                },
                "description": "An array of partial user records for each user in the organization.",
                "example": "Skyswitch Training"
              },
              "LicenseType": {
                "type": "string",
                "description": "The id of the plan type for this organization.",
                "example": "cloudmessage-pro"
              },
              "LicenseQuantity": {
                "type": "number",
                "description": "(Deprecated) Ignore this property, it will be removed.",
                "example": 2
              },
              "UserQuantity": {
                "type": "number",
                "description": "The number of billable users for this organization.",
                "example": 2
              }
            }
          },
          "description": "An array of each organization in the tenant and it's user breakdown."
        },
        "UserBreakdown": {
          "type": "array",
          "example": [
            {
              "fullName": "John Doe",
              "email": "john.doe@example.com",
              "phoneNumber": "+1234567890",
              "accountType": "User",
              "licenseType": "cloudmessage-pro",
              "organizationName": "Example Organization",
              "organizationExternalId": "example-org-123"
            }
          ],
          "items": {
            "type": "object",
            "properties": {
              "fullName": {
                "type": "string",
                "description": "The full name of the user.",
                "example": "John Doe"
              },
              "email": {
                "type": "string",
                "description": "The email address of the user.",
                "example": "john.doe@example.com"
              },
              "phoneNumber": {
                "type": "string",
                "description": "The phone number of the user.",
                "example": 1234567890
              },
              "accountType": {
                "type": "string",
                "description": "The type of account for the user.",
                "example": "User"
              },
              "licenseType": {
                "type": "string",
                "description": "The license type assigned to the user.",
                "example": "cloudmessage-pro"
              },
              "organizationName": {
                "type": "string",
                "description": "The name of the organization the user belongs to.",
                "example": "Example Organization"
              },
              "organizationExternalId": {
                "type": "string",
                "description": "The external ID of the organization the user belongs to.",
                "example": "example-org-123"
              }
            }
          },
          "description": "An array of user details for the \"Licenses by User\" report."
        },
        "UserQuantity": {
          "type": "number",
          "example": 10,
          "description": "The total count of users in the tenant."
        }
      }
    }
  },
  "x-webhooks": {
    "relayWebhook": {
      "post": {
        "summary": "Message Event",
        "description": "Relay sends a POST to the URL stored in the `relayWebhook` attribute of the user for which a message is sent or received. \n",
        "tags": [
          "webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "MessageID": {
                    "type": "string",
                    "description": "The unique message ID"
                  },
                  "ConversationID": {
                    "type": "string",
                    "description": "The unique contact ID"
                  },
                  "ToNumber": {
                    "description": "For Group MMS, this will be an array of strings. For all other messages, this will be a single string.",
                    "oneOf": [
                      {
                        "type": "string",
                        "description": "The number the message was sent to"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "description": "Each number in the group the message was sent to"
                        }
                      }
                    ]
                  },
                  "FromNumber": {
                    "type": "string",
                    "description": "The number the message was sent from"
                  },
                  "MessageBody": {
                    "type": "string",
                    "description": "The message body"
                  },
                  "MessageDirection": {
                    "type": "string",
                    "description": "The message direction (either \"in\" or \"out\")"
                  },
                  "TextableUserID": {
                    "type": "string",
                    "description": "The user id of the account that sent or received the message"
                  },
                  "TextableOrganizationID": {
                    "type": "string",
                    "description": "The unique identifier for the Textable organization"
                  },
                  "ContactName": {
                    "type": "string",
                    "description": "The Full Name property of the contact"
                  },
                  "ContactEmail": {
                    "type": "string",
                    "description": "The e-mail address of the contact (if available).  Not present for group messages."
                  },
                  "AccessToken": {
                    "type": "string",
                    "description": "The access token for the user",
                    "nullable": true
                  },
                  "Media": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "All MMS attachment urls associated with the message (if any)"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return a 200 status to indicate that the data was received successfully"
          }
        }
      }
    }
  }
}