{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/codai-ro/json-schema/codai-ro-feed-post-schema.json",
  "title": "FeedPost",
  "description": "A feed post. The only author identity exposed is the public username.",
  "x-generated": "2026-11-10",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/codai-ro-feed-api-openapi.yml#/components/schemas/FeedPost",
  "type": "object",
  "required": [
    "id",
    "kind",
    "body",
    "link_url",
    "images",
    "author",
    "like_count",
    "liked_by_me",
    "status",
    "moderation_reason",
    "created_at",
    "lang",
    "comment_count",
    "link_preview",
    "tags",
    "mentions",
    "media",
    "public_url"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "kind": {
      "type": "string",
      "enum": [
        "project",
        "seeking",
        "idea"
      ]
    },
    "body": {
      "type": "string",
      "maxLength": 2000
    },
    "link_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri"
    },
    "images": {
      "type": "array",
      "maxItems": 4,
      "items": {
        "$ref": "#/$defs/FeedPostImage"
      }
    },
    "author": {
      "type": "object",
      "required": [
        "username",
        "is_me",
        "badge"
      ],
      "properties": {
        "username": {
          "type": [
            "string",
            "null"
          ]
        },
        "is_me": {
          "type": "boolean"
        },
        "badge": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "team",
            null
          ],
          "description": "`team` for official codai accounts; otherwise null."
        }
      }
    },
    "like_count": {
      "type": "integer",
      "minimum": 0
    },
    "liked_by_me": {
      "type": "boolean"
    },
    "status": {
      "type": "string",
      "enum": [
        "visible",
        "hidden",
        "removed"
      ],
      "description": "`hidden` (pending review) and `removed` are only ever returned to the author."
    },
    "moderation_reason": {
      "type": [
        "string",
        "null"
      ],
      "description": "Statement of reasons from a moderator; author only."
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "lang": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "en",
        "ro",
        null
      ],
      "description": "Language of the post (`en`, `ro`) or null when it is for everyone."
    },
    "comment_count": {
      "type": "integer",
      "minimum": 0,
      "description": "Number of comments on the post, hidden ones included."
    },
    "link_preview": {
      "oneOf": [
        {
          "$ref": "#/$defs/FeedLinkPreview"
        },
        {
          "type": "null"
        }
      ],
      "description": "Preview of `link_url` fetched when the post was created; null when there is no link or it could not be fetched."
    },
    "tags": {
      "type": "array",
      "maxItems": 10,
      "description": "Hashtags parsed from the body (lowercase, without diacritics, in body order). Render `#tag` as a link to the feed filtered by `tag`.",
      "items": {
        "type": "string"
      }
    },
    "mentions": {
      "type": "array",
      "maxItems": 5,
      "description": "Usernames mentioned in the body that exist (lowercase). Only these `@username` render as profile links.",
      "items": {
        "type": "string"
      }
    },
    "media": {
      "oneOf": [
        {
          "$ref": "#/$defs/FeedPostMedia"
        },
        {
          "type": "null"
        }
      ],
      "description": "Video or audio of a C2PA-signed Studio render when `link_url` is a Studio view share; otherwise null."
    },
    "public_url": {
      "type": [
        "string",
        "null"
      ],
      "format": "uri",
      "description": "Public page on codai.ro when the author turned on the public web (`settings.feed.publicWeb`); otherwise null."
    }
  },
  "$defs": {
    "FeedLinkPreview": {
      "type": "object",
      "description": "Preview of a link, fetched once when the post was created.",
      "required": [
        "url",
        "title",
        "description",
        "site_name",
        "image_url"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri",
          "description": "The link the preview card opens."
        },
        "title": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 200,
          "description": "Page title (up to 200 characters)."
        },
        "description": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 300,
          "description": "Page description (up to 300 characters)."
        },
        "site_name": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 80,
          "description": "Site name (up to 80 characters)."
        },
        "image_url": {
          "type": [
            "string",
            "null"
          ],
          "format": "uri",
          "description": "Public preview image (`GET /v1/feed/previews/{postId}`), or null."
        }
      }
    },
    "FeedPostImage": {
      "type": "object",
      "required": [
        "url"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        },
        "width": {
          "type": "integer"
        },
        "height": {
          "type": "integer"
        }
      }
    },
    "FeedPostMedia": {
      "type": "object",
      "description": "Inline media of a post: a C2PA-signed Studio render.",
      "required": [
        "kind",
        "url",
        "poster_url",
        "width",
        "height",
        "duration_ms",
        "c2pa"
      ],
      "properties": {
        "kind": {
          "type": "string",
          "enum": [
            "video",
            "audio"
          ]
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "Public URL (`GET /v1/feed/media/{postId}`) that redirects to a 10-minute signed URL."
        },
        "poster_url": {
          "type": [
            "string",
            "null"
          ],
          "format": "uri",
          "description": "Poster frame (`GET /v1/feed/media/{postId}/poster`), or null."
        },
        "width": {
          "type": [
            "integer",
            "null"
          ]
        },
        "height": {
          "type": [
            "integer",
            "null"
          ]
        },
        "duration_ms": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "c2pa": {
          "type": "boolean",
          "enum": [
            true
          ],
          "description": "Always true: only renders with Content Credentials (C2PA) are attached."
        }
      }
    }
  }
}