{
  "openapi": "3.1.0",
  "info": {
    "title": "Hubzone API",
    "version": "1.0.0",
    "description": "Read and write your Hubzone records from your own systems."
  },
  "servers": [
    {
      "url": "https://hubzone.app/api",
      "description": "Production"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key made under Settings > Developers (hzk_...)."
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/open/v1/me": {
      "get": {
        "operationId": "getKey",
        "tags": [
          "Key"
        ],
        "summary": "Key information",
        "description": "Shows what the key may do and the limits per kind of call.\n\nPermission: any key",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "The key.",
            "content": {
              "application/json": {
                "example": {
                  "keyId": "3f0c8f0e-2b1a-4c55-9a38-0d6c1c9d7e11",
                  "scopes": [
                    "contacts.read",
                    "contacts.write"
                  ],
                  "limits": {
                    "get": {
                      "label": "Read one record",
                      "perMinute": 600
                    }
                  },
                  "allScopes": 14
                }
              }
            }
          },
          "401": {
            "description": "No key, a wrong key, or a revoked or expired key."
          },
          "429": {
            "description": "Too many calls: wait for Retry-After."
          }
        }
      }
    },
    "/open/v1/properties/{type}": {
      "get": {
        "operationId": "listProperties",
        "tags": [
          "Properties"
        ],
        "summary": "List properties",
        "description": "The properties (fields) of a kind of record: their names, types and, for choice lists, the options. Use the names in create, change and search calls.\n\nPermission: {type}.read",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The kind of record.",
            "schema": {
              "type": "string",
              "enum": [
                "contacts",
                "companies",
                "deals",
                "tickets",
                "products",
                "orders",
                "calls"
              ]
            },
            "example": "contacts"
          }
        ],
        "responses": {
          "200": {
            "description": "The properties.",
            "content": {
              "application/json": {
                "example": {
                  "properties": [
                    {
                      "key": "email",
                      "type": "text",
                      "label_i18n": {
                        "en": "Email",
                        "tr": "E-posta"
                      },
                      "options": null
                    },
                    {
                      "key": "lifecycle_stage",
                      "type": "enum",
                      "label_i18n": {
                        "en": "Lifecycle stage",
                        "tr": "Yaşam döngüsü aşaması"
                      },
                      "options": [
                        {
                          "value": "lead",
                          "label_i18n": {
                            "en": "Lead"
                          }
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No key, a wrong key, or a revoked or expired key."
          },
          "403": {
            "description": "The key lacks the permission for this call."
          },
          "404": {
            "description": "Not found (or it belongs to another workspace)."
          },
          "429": {
            "description": "Too many calls: wait for Retry-After."
          }
        }
      }
    },
    "/open/v1/objects/{type}": {
      "get": {
        "operationId": "listRecords",
        "tags": [
          "Records"
        ],
        "summary": "List or find records",
        "description": "Records of one kind, newest activity first, a page at a time. \"q\" finds records whose text properties contain the text. For the next page send the \"after\" value from the answer.\n\nPermission: {type}.read",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The kind of record.",
            "schema": {
              "type": "string",
              "enum": [
                "contacts",
                "companies",
                "deals",
                "tickets",
                "products",
                "orders",
                "calls"
              ]
            },
            "example": "contacts"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Records per page (default 25).",
            "schema": {
              "type": "integer"
            },
            "example": "25"
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "description": "The cursor of the next page, from the previous answer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Text to find.",
            "schema": {
              "type": "string"
            },
            "example": "ada"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of records. \"paging.next.after\" is null on the last page.",
            "content": {
              "application/json": {
                "example": {
                  "results": [
                    {
                      "id": "8a3b2f64-1c9d-4e05-b7a1-3f2c9d0e4a12",
                      "objectType": "contacts",
                      "properties": {
                        "first_name": "Ada",
                        "last_name": "Lovelace",
                        "email": "ada@example.com"
                      },
                      "ownerId": "5d1f0f3e-7e0a-4b8e-9a50-aa14d3c9b2f1",
                      "isPrivate": false,
                      "createdAt": "2026-11-10T09:30:00.000Z",
                      "updatedAt": "2026-11-10T09:30:00.000Z",
                      "pipelineId": null,
                      "stageId": null,
                      "stageChangedAt": null,
                      "lastActivityAt": null
                    }
                  ],
                  "paging": {
                    "next": {
                      "after": "eyJ2IjoxfQ"
                    }
                  },
                  "total": {
                    "value": 1,
                    "capped": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the message says why.",
            "content": {
              "application/json": {
                "example": {
                  "statusCode": 400,
                  "message": "properties.email: must be a valid e-mail address",
                  "error": "Bad Request"
                }
              }
            }
          },
          "401": {
            "description": "No key, a wrong key, or a revoked or expired key."
          },
          "403": {
            "description": "The key lacks the permission for this call."
          },
          "429": {
            "description": "Too many calls: wait for Retry-After."
          }
        }
      },
      "post": {
        "operationId": "createRecord",
        "tags": [
          "Records"
        ],
        "summary": "Create a record",
        "description": "Creates a record. Send properties under the names from \"List properties\". Only properties, ownerId, stageId and pipelineId are accepted. The key's person owns the record unless ownerId says otherwise. To log a phone call use the calls endpoint instead.\n\nPermission: {type}.write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The kind of record.",
            "schema": {
              "type": "string",
              "enum": [
                "contacts",
                "companies",
                "deals",
                "tickets",
                "products",
                "orders",
                "calls"
              ]
            },
            "example": "contacts"
          }
        ],
        "requestBody": {
          "required": true,
          "description": "\"properties\" is required.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "properties": {
                  "first_name": "Ada",
                  "last_name": "Lovelace",
                  "email": "ada@example.com"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new record.",
            "content": {
              "application/json": {
                "example": {
                  "id": "8a3b2f64-1c9d-4e05-b7a1-3f2c9d0e4a12",
                  "objectType": "contacts",
                  "properties": {
                    "first_name": "Ada",
                    "last_name": "Lovelace",
                    "email": "ada@example.com"
                  },
                  "ownerId": "5d1f0f3e-7e0a-4b8e-9a50-aa14d3c9b2f1",
                  "isPrivate": false,
                  "createdAt": "2026-11-10T09:30:00.000Z",
                  "updatedAt": "2026-11-10T09:30:00.000Z",
                  "pipelineId": null,
                  "stageId": null,
                  "stageChangedAt": null,
                  "lastActivityAt": null
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the message says why.",
            "content": {
              "application/json": {
                "example": {
                  "statusCode": 400,
                  "message": "properties.email: must be a valid e-mail address",
                  "error": "Bad Request"
                }
              }
            }
          },
          "401": {
            "description": "No key, a wrong key, or a revoked or expired key."
          },
          "403": {
            "description": "The key lacks the permission for this call."
          },
          "429": {
            "description": "Too many calls: wait for Retry-After."
          }
        }
      }
    },
    "/open/v1/objects/{type}/search": {
      "post": {
        "operationId": "searchRecords",
        "tags": [
          "Records"
        ],
        "summary": "Search records",
        "description": "Search with filters, sorting and a text query. A record matches when it satisfies every filter in \"filters\". Operators: eq, neq, gt, gte, lt, lte, contains, starts_with, in, exists, not_exists.\n\nPermission: {type}.read",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The kind of record.",
            "schema": {
              "type": "string",
              "enum": [
                "contacts",
                "companies",
                "deals",
                "tickets",
                "products",
                "orders",
                "calls"
              ]
            },
            "example": "contacts"
          }
        ],
        "requestBody": {
          "required": true,
          "description": "All fields are optional.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "query": "renewal",
                "filters": [
                  {
                    "property": "amount",
                    "op": "gte",
                    "value": 1000
                  }
                ],
                "sort": {
                  "property": "amount",
                  "direction": "desc"
                },
                "limit": 25
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A page of records, as in the list call.",
            "content": {
              "application/json": {
                "example": {
                  "results": [
                    {
                      "id": "8a3b2f64-1c9d-4e05-b7a1-3f2c9d0e4a12",
                      "objectType": "contacts",
                      "properties": {
                        "first_name": "Ada",
                        "last_name": "Lovelace",
                        "email": "ada@example.com"
                      },
                      "ownerId": "5d1f0f3e-7e0a-4b8e-9a50-aa14d3c9b2f1",
                      "isPrivate": false,
                      "createdAt": "2026-11-10T09:30:00.000Z",
                      "updatedAt": "2026-11-10T09:30:00.000Z",
                      "pipelineId": null,
                      "stageId": null,
                      "stageChangedAt": null,
                      "lastActivityAt": null
                    }
                  ],
                  "paging": null,
                  "total": {
                    "value": 1,
                    "capped": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the message says why.",
            "content": {
              "application/json": {
                "example": {
                  "statusCode": 400,
                  "message": "properties.email: must be a valid e-mail address",
                  "error": "Bad Request"
                }
              }
            }
          },
          "401": {
            "description": "No key, a wrong key, or a revoked or expired key."
          },
          "403": {
            "description": "The key lacks the permission for this call."
          },
          "429": {
            "description": "Too many calls: wait for Retry-After."
          }
        }
      }
    },
    "/open/v1/objects/{type}/{id}": {
      "get": {
        "operationId": "getRecord",
        "tags": [
          "Records"
        ],
        "summary": "Read one record",
        "description": "One record with all its properties.\n\nPermission: {type}.read",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The kind of record.",
            "schema": {
              "type": "string",
              "enum": [
                "contacts",
                "companies",
                "deals",
                "tickets",
                "products",
                "orders",
                "calls"
              ]
            },
            "example": "contacts"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The id of the record.",
            "schema": {
              "type": "string"
            },
            "example": "8a3b2f64-1c9d-4e05-b7a1-3f2c9d0e4a12"
          }
        ],
        "responses": {
          "200": {
            "description": "The record.",
            "content": {
              "application/json": {
                "example": {
                  "id": "8a3b2f64-1c9d-4e05-b7a1-3f2c9d0e4a12",
                  "objectType": "contacts",
                  "properties": {
                    "first_name": "Ada",
                    "last_name": "Lovelace",
                    "email": "ada@example.com"
                  },
                  "ownerId": "5d1f0f3e-7e0a-4b8e-9a50-aa14d3c9b2f1",
                  "isPrivate": false,
                  "createdAt": "2026-11-10T09:30:00.000Z",
                  "updatedAt": "2026-11-10T09:30:00.000Z",
                  "pipelineId": null,
                  "stageId": null,
                  "stageChangedAt": null,
                  "lastActivityAt": null
                }
              }
            }
          },
          "401": {
            "description": "No key, a wrong key, or a revoked or expired key."
          },
          "403": {
            "description": "The key lacks the permission for this call."
          },
          "404": {
            "description": "Not found (or it belongs to another workspace)."
          },
          "429": {
            "description": "Too many calls: wait for Retry-After."
          }
        }
      },
      "patch": {
        "operationId": "updateRecord",
        "tags": [
          "Records"
        ],
        "summary": "Change a record",
        "description": "Changes the properties you send; the others stay as they are. Send a property as null to clear it. A deal or ticket moves to another stage with stageId.\n\nPermission: {type}.write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "The kind of record.",
            "schema": {
              "type": "string",
              "enum": [
                "contacts",
                "companies",
                "deals",
                "tickets",
                "products",
                "orders",
                "calls"
              ]
            },
            "example": "contacts"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The id of the record.",
            "schema": {
              "type": "string"
            },
            "example": "8a3b2f64-1c9d-4e05-b7a1-3f2c9d0e4a12"
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Send only what changes.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "properties": {
                  "job_title": "Mathematician"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The changed record.",
            "content": {
              "application/json": {
                "example": {
                  "id": "8a3b2f64-1c9d-4e05-b7a1-3f2c9d0e4a12",
                  "objectType": "contacts",
                  "properties": {
                    "first_name": "Ada",
                    "last_name": "Lovelace",
                    "email": "ada@example.com",
                    "job_title": "Mathematician"
                  },
                  "ownerId": "5d1f0f3e-7e0a-4b8e-9a50-aa14d3c9b2f1",
                  "isPrivate": false,
                  "createdAt": "2026-11-10T09:30:00.000Z",
                  "updatedAt": "2026-11-10T09:30:00.000Z",
                  "pipelineId": null,
                  "stageId": null,
                  "stageChangedAt": null,
                  "lastActivityAt": null
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the message says why.",
            "content": {
              "application/json": {
                "example": {
                  "statusCode": 400,
                  "message": "properties.email: must be a valid e-mail address",
                  "error": "Bad Request"
                }
              }
            }
          },
          "401": {
            "description": "No key, a wrong key, or a revoked or expired key."
          },
          "403": {
            "description": "The key lacks the permission for this call."
          },
          "404": {
            "description": "Not found (or it belongs to another workspace)."
          },
          "429": {
            "description": "Too many calls: wait for Retry-After."
          }
        }
      }
    },
    "/open/v1/calls": {
      "post": {
        "operationId": "logCall",
        "tags": [
          "Calls"
        ],
        "summary": "Log a phone call",
        "description": "For phones and phone systems: the call is tied to the contact with that phone number and shows on their timeline. Audio is never sent. With externalId a call you send twice is stored once.\n\nPermission: calls.write",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "description": "phoneNumber is required. direction: inbound or outbound. outcome: busy, connected, left_live_message, left_voicemail, meeting_booked, no_answer or wrong_number.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "phoneNumber": "+90 532 000 00 00",
                "direction": "outbound",
                "startedAt": "2026-11-10T09:30:00Z",
                "durationSeconds": 184,
                "outcome": "connected",
                "note": "Asked for a quote",
                "externalId": "pbx-7781"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The call and the contact it was tied to (linked is false when no contact has that number).",
            "content": {
              "application/json": {
                "example": {
                  "id": "c1d2e3f4-0000-4000-8000-000000000001",
                  "activityId": "a1b2c3d4-0000-4000-8000-000000000002",
                  "contactId": "8a3b2f64-1c9d-4e05-b7a1-3f2c9d0e4a12",
                  "linked": true,
                  "duplicate": false
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the message says why.",
            "content": {
              "application/json": {
                "example": {
                  "statusCode": 400,
                  "message": "properties.email: must be a valid e-mail address",
                  "error": "Bad Request"
                }
              }
            }
          },
          "401": {
            "description": "No key, a wrong key, or a revoked or expired key."
          },
          "403": {
            "description": "The key lacks the permission for this call."
          },
          "429": {
            "description": "Too many calls: wait for Retry-After."
          }
        }
      }
    },
    "/public/events/{eventKey}": {
      "post": {
        "operationId": "sendEvent",
        "tags": [
          "Events"
        ],
        "summary": "Send a custom event",
        "description": "Records one occurrence of a custom event you defined. No Authorization header: the event key in the address is the credential. See the Custom events guide.\n\nPermission: event key",
        "security": [],
        "parameters": [
          {
            "name": "eventKey",
            "in": "path",
            "required": true,
            "description": "The key of the event (starts with hze_), shown once when you make the event.",
            "schema": {
              "type": "string"
            },
            "example": "hze_your_event_key"
          }
        ],
        "requestBody": {
          "required": true,
          "description": "email is required.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "email": "person@example.com",
                "properties": {
                  "plan": "pro",
                  "seats": 5
                },
                "occurredAt": "2026-11-10T09:30:00Z"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Stored. linkedToContact says whether a contact has that e-mail address.",
            "content": {
              "application/json": {
                "example": {
                  "id": "1b7e0c52-6f0e-4c7a-9a43-2d5e9d1f0a77",
                  "linkedToContact": true
                }
              }
            }
          },
          "400": {
            "description": "The request is not valid; the message says why.",
            "content": {
              "application/json": {
                "example": {
                  "statusCode": 400,
                  "message": "properties.email: must be a valid e-mail address",
                  "error": "Bad Request"
                }
              }
            }
          },
          "404": {
            "description": "Unknown event key."
          },
          "429": {
            "description": "Too many calls: wait for Retry-After."
          }
        }
      }
    }
  }
}