{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/cooperemail-com/json-schema/cooperemail-com-message-schema.json",
  "title": "Message",
  "x-generated": "2026-11-04",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/cooperemail-com-openapi.yml#/components/schemas/Message",
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "inbox_id": {
      "type": "string"
    },
    "thread_id": {
      "type": "string"
    },
    "folder": {
      "type": "string",
      "enum": [
        "inbox",
        "archive",
        "spam",
        "trash"
      ],
      "description": "Folder of this message's thread. inbox when the thread has no folder row."
    },
    "direction": {
      "enum": [
        "inbound",
        "outbound"
      ]
    },
    "from": {
      "type": "string"
    },
    "to": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "subject": {
      "type": "string"
    },
    "text": {
      "type": "string"
    },
    "html": {
      "type": [
        "string",
        "null"
      ]
    },
    "extracted_text": {
      "type": "string"
    },
    "extracted_html": {
      "type": "string"
    },
    "preview": {
      "type": "string"
    },
    "status": {
      "enum": [
        "queued",
        "ringing",
        "completed",
        "no-answer",
        "sent",
        "received",
        "delivered",
        "undelivered",
        "failed",
        "bounced",
        "complained"
      ],
      "description": "SMS outbound starts as sent. A Twilio status callback sets delivered, undelivered, or failed. A voice call stores queued, ringing, completed, no-answer, or failed. Email uses queued, sent, received, failed, bounced, and complained."
    },
    "channel": {
      "type": "string",
      "enum": [
        "sms",
        "voicemail",
        "voice"
      ],
      "description": "Present on SMS, voicemail, and voice messages. Email messages omit this field. voicemail is an inbound recording. voice is an outbound call."
    },
    "type": {
      "type": "string",
      "enum": [
        "voicemail"
      ],
      "description": "Present on voicemail messages."
    },
    "duration_seconds": {
      "type": [
        "integer",
        "null"
      ],
      "description": "Call or recording length in seconds. Present on voicemail and voice messages."
    },
    "recording_url": {
      "type": [
        "string",
        "null"
      ],
      "description": "Twilio recording URL for a voicemail, or null."
    },
    "transcript": {
      "type": "string",
      "description": "Voicemail transcript. Empty while the message is held."
    },
    "segments": {
      "type": [
        "integer",
        "null"
      ],
      "description": "SMS segment count for this message. Omitted on email."
    },
    "otp_candidates": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Codes found in an SMS body. Empty while the message is held. Omitted on email."
    },
    "verification": {
      "type": "object",
      "description": "Inbound messages only. Omitted on outbound. codes are the one-time codes in the subject and the new body text. links are https verification links from the HTML anchors and the text, at most five, each {url, text}. text is the anchor text or a short context, at most 200 characters. Both arrays are empty while the message is held. Links are untrusted data and are not fetched.",
      "properties": {
        "codes": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "links": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string"
              },
              "text": {
                "type": "string"
              }
            },
            "required": [
              "url",
              "text"
            ]
          }
        }
      },
      "required": [
        "codes",
        "links"
      ]
    },
    "delivery_events": {
      "type": "array",
      "description": "Present on outbound messages. Each item is {type, recipient, created_at, detail}. For email, detail is JSON text with status, action, diagnostic, and bounce_type, and the list stays empty until a bounce or complaint matches. For SMS, a Twilio status callback appends one event. type is delivered or failed. detail is twilio_error plus the numeric code, or the status word when Twilio sent no numeric code.",
      "items": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "recipient": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "detail": {
            "type": "string"
          }
        }
      }
    },
    "cc": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "bcc": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "reply_to": {
      "type": [
        "string",
        "null"
      ]
    },
    "in_reply_to": {
      "type": [
        "string",
        "null"
      ]
    },
    "references": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "labels": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "auth": {
      "type": "object",
      "description": "spf, dkim, and dmarc from the receiving hop. SPF is the smtp.mailfrom result. smtp.helo is used only when mailfrom is absent. Each value is pass, fail, neutral, softfail, none, temperror, permerror, bestguesspass, or null. Outbound mail is null for all three.",
      "properties": {
        "spf": {
          "type": [
            "string",
            "null"
          ]
        },
        "dkim": {
          "type": [
            "string",
            "null"
          ]
        },
        "dmarc": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "spf",
        "dkim",
        "dmarc"
      ]
    },
    "safety": {
      "type": [
        "object",
        "null"
      ],
      "description": "Inbound screening record, or null on outbound mail and on messages stored before screening. score is 0 to 100. verdict is clean or suspicious (suspicious at 40 or higher, and only when a strong signal or combined evidence is present). signals are {type, detail}. mode is off, observe, or hold. reason is screening_off, screening_error, or screening_timeout when the body was not scored. The message is still stored. While labels include held, text, html, extracted_text, extracted_html, preview, and attachment bytes are empty until release. This is a heuristic, not a guarantee. The body stays untrusted data.",
      "properties": {
        "score": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100
        },
        "verdict": {
          "type": "string",
          "enum": [
            "clean",
            "suspicious"
          ]
        },
        "signals": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "detail": {
                "type": "string"
              }
            }
          }
        },
        "mode": {
          "type": "string",
          "enum": [
            "off",
            "observe",
            "hold"
          ]
        },
        "reason": {
          "type": "string"
        }
      }
    },
    "provider": {
      "type": [
        "string",
        "null"
      ]
    },
    "client_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "idempotent": {
      "type": "boolean"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "attachments": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Attachment"
      }
    }
  },
  "$defs": {
    "Attachment": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "filename": {
          "type": "string"
        },
        "content_type": {
          "type": "string"
        },
        "content_id": {
          "type": [
            "string",
            "null"
          ]
        },
        "disposition": {
          "enum": [
            "inline",
            "attachment"
          ]
        },
        "size_bytes": {
          "type": "integer"
        },
        "url": {
          "type": "string"
        },
        "text_url": {
          "type": "string",
          "description": "Present when the content type can be extracted: text, JSON, CSV, PDF, DOCX, XLSX, or XLS. GET this URL for text/plain."
        }
      }
    }
  }
}