{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/postzen-dev/json-schema/postzen-dev-contact-schema.json",
  "title": "Contact",
  "description": "A profile-owned person. Maximum 5000 contacts per user and 20 channels per contact. Absent optional fields are returned as null. Message history is not backfilled.",
  "x-generated": "2026-10-31",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/postzen-dev-openapi.json#/components/schemas/Contact",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Contact id."
    },
    "profileId": {
      "type": "string",
      "description": "Owning profile id; immutable and must be in the API key scope."
    },
    "name": {
      "type": "string",
      "description": "Trimmed contact name, 1–200 characters.",
      "minLength": 1,
      "maxLength": 200
    },
    "email": {
      "type": [
        "string",
        "null"
      ],
      "description": "Trimmed lowercase email; unique within its profile.",
      "maxLength": 254,
      "pattern": "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"
    },
    "company": {
      "type": [
        "string",
        "null"
      ],
      "description": "Company name, at most 200 characters.",
      "maxLength": 200
    },
    "avatarUrl": {
      "type": [
        "string",
        "null"
      ],
      "description": "Public HTTPS avatar URL, canonicalized on PATCH; inbox avatars are stored as supplied by the platform.",
      "format": "uri",
      "maxLength": 2048
    },
    "tags": {
      "type": "array",
      "description": "At most 50 tags, trimmed and deduplicated case-insensitively, preserving original case. Send [] to clear.",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 50
      },
      "maxItems": 50
    },
    "isSubscribed": {
      "type": "boolean",
      "description": "Contact subscription state. False prevents comment automation sends.",
      "default": true
    },
    "isBlocked": {
      "type": "boolean",
      "description": "Blocked contacts cannot receive comment automation sends.",
      "default": false
    },
    "notes": {
      "type": [
        "string",
        "null"
      ],
      "description": "Free-form notes, at most 5000 characters.",
      "maxLength": 5000
    },
    "customFields": {
      "type": [
        "object",
        "null"
      ],
      "description": "At most 50 keys of 1–64 characters. Keys follow Convex record rules: printable ASCII, not starting with $ or _. Values are strings (at most 1000 characters), finite numbers, booleans, or null. PATCH replaces the entire object.",
      "maxProperties": 50,
      "propertyNames": {
        "minLength": 1,
        "maxLength": 64,
        "pattern": "^(?![$_])[\\x20-\\x7e]+$"
      },
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "maxLength": 1000
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          },
          {
            "type": "null"
          }
        ]
      }
    },
    "messagesSentCount": {
      "type": "integer",
      "description": "Messages sent by the connected account, including automation DMs. Counters start when Contacts ships; history is not backfilled.",
      "minimum": 0
    },
    "messagesReceivedCount": {
      "type": "integer",
      "description": "Messages received from this person since Contacts ships; re-syncing stored messages does not increment this count.",
      "minimum": 0
    },
    "lastMessageSentAt": {
      "type": [
        "string",
        "null"
      ],
      "description": "Latest counted outbound message time, or null.",
      "format": "date-time"
    },
    "lastMessageReceivedAt": {
      "type": [
        "string",
        "null"
      ],
      "description": "Latest counted inbound message time, or null.",
      "format": "date-time"
    },
    "source": {
      "type": "string",
      "description": "How this contact first came to exist; informational and immutable.",
      "enum": [
        "api",
        "inbox",
        "automation"
      ]
    },
    "createdAt": {
      "type": "string",
      "description": "Contact creation time.",
      "format": "date-time"
    },
    "updatedAt": {
      "type": "string",
      "description": "Latest contact update time.",
      "format": "date-time"
    }
  },
  "required": [
    "id",
    "profileId",
    "name",
    "email",
    "company",
    "avatarUrl",
    "tags",
    "isSubscribed",
    "isBlocked",
    "notes",
    "customFields",
    "messagesSentCount",
    "messagesReceivedCount",
    "lastMessageSentAt",
    "lastMessageReceivedAt",
    "source",
    "createdAt",
    "updatedAt"
  ]
}