{
  "info": {
    "title": "TRIP API",
    "version": "0.2.0",
    "description": "Tenant-scoped data exports for customer analytics integrations. Each request uses an analytics API token; its authorized project determines the tenant.\n\n# Authentication\n\nSend the token in the `Authorization` header, as `Bearer <token>` or as the raw token. Only `analytics` tokens can read these endpoints. The token's project selects the tenant; there is no project or table parameter.\n\n# Response format\n\nSuccessful responses contain the dataset directly, without a `{data: ...}` envelope. Legacy datasets can return `null` when no rows exist; Access, Auth analytics, and News datasets return `[]`."
  },
  "openapi": "3.0.0",
  "paths": {
    "/access": {
      "get": {
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "properties": {
                      "lastLoginTime": {
                        "type": "string"
                      },
                      "registerDate": {
                        "type": "string"
                      },
                      "userId": {
                        "type": "string"
                      }
                    },
                    "type": "object",
                    "required": [
                      "lastLoginTime",
                      "registerDate",
                      "userId"
                    ]
                  },
                  "type": "array"
                },
                "example": [
                  {
                    "userId": "user-example",
                    "registerDate": "2026-09-01T09:00:00Z",
                    "lastLoginTime": "2026-09-30T18:00:00Z"
                  }
                ]
              }
            },
            "description": "Dataset array; an empty result is []."
          },
          "401": {
            "description": "Missing `Authorization` header (API Gateway responds `{\"message\":\"Unauthorized\"}`), or a valid token whose type is not `analytics`, such as an `authentication` token (example below).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                },
                "example": {
                  "name": "Unauthorized",
                  "message": "Authentication required",
                  "data": null
                }
              }
            }
          },
          "403": {
            "description": "The authorizer rejected the token: unknown, inactive, expired, or a denied type such as `mcp`."
          },
          "500": {
            "description": "Tenant configuration, token lookup, or data read failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Unable to read tenant data"
                }
              }
            }
          }
        },
        "description": "Returns user registration and latest login values from the authorized tenant. A successful empty result is [].",
        "tags": [
          "Users"
        ],
        "operationId": "queryAccess",
        "summary": "Query account access records",
        "security": [
          {
            "TripToken": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl --fail-with-body \\\n  -H \"Authorization: Bearer <analytics-token>\" \\\n  \"https://trip.dev.2gether.dev.br/access\""
          }
        ]
      }
    },
    "/auth/analytics": {
      "get": {
        "parameters": [
          {
            "name": "eventKind",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "LOGIN",
                "REGISTER"
              ]
            },
            "description": "Required event kind."
          },
          {
            "name": "granularity",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "DAILY",
                "WEEKLY",
                "MONTHLY"
              ]
            },
            "description": "Required time granularity."
          },
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ios",
                "android",
                "web"
              ]
            },
            "description": "Optional platform series; normalized to lowercase. Omit for project totals. An explicitly empty value is invalid."
          }
        ],
        "responses": {
          "200": {
            "description": "Dataset array; an empty result is [].",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "projectId": {
                        "type": "string"
                      },
                      "eventKind": {
                        "type": "string",
                        "enum": [
                          "LOGIN",
                          "REGISTER"
                        ]
                      },
                      "scope": {
                        "type": "string",
                        "enum": [
                          "PROJECT",
                          "PLATFORM"
                        ]
                      },
                      "granularity": {
                        "type": "string",
                        "enum": [
                          "DAILY",
                          "WEEKLY",
                          "MONTHLY"
                        ]
                      },
                      "periodStart": {
                        "type": "string",
                        "description": "Stored UTC period start; rows are ascending."
                      },
                      "count": {
                        "type": "integer"
                      },
                      "dau": {
                        "type": "integer",
                        "description": "Only present for daily project LOGIN records, including zero. Platform counts are not unique-user counts."
                      },
                      "platform": {
                        "type": "string",
                        "enum": [
                          "ios",
                          "android",
                          "web"
                        ]
                      },
                      "updatedAt": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "projectId",
                      "eventKind",
                      "scope",
                      "granularity",
                      "periodStart",
                      "count",
                      "updatedAt"
                    ]
                  }
                },
                "example": [
                  {
                    "projectId": "tenant-example",
                    "eventKind": "LOGIN",
                    "scope": "PROJECT",
                    "granularity": "DAILY",
                    "periodStart": "2026-09-30",
                    "count": 8,
                    "dau": 5,
                    "updatedAt": "2026-09-30T18:00:00Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Required parameter missing, invalid enum/boolean, or invalid paired RFC3339 bounds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Invalid query parameter"
                }
              }
            }
          },
          "401": {
            "description": "Missing `Authorization` header (API Gateway responds `{\"message\":\"Unauthorized\"}`), or a valid token whose type is not `analytics`, such as an `authentication` token (example below).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Authentication required"
                }
              }
            }
          },
          "403": {
            "description": "The authorizer rejected the token: unknown, inactive, expired, or a denied type such as `mcp`."
          },
          "500": {
            "description": "Tenant configuration, token lookup, or data read failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Unable to read tenant data"
                }
              }
            }
          }
        },
        "description": "Enum values are case-insensitive and trimmed. Returns all stored periods for one event kind and granularity. An omitted platform selects project totals. No per-user or global series are exposed.",
        "tags": [
          "Auth analytics"
        ],
        "operationId": "queryAuthAnalytics",
        "summary": "Query authentication aggregates",
        "security": [
          {
            "TripToken": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl --fail-with-body \\\n  -H \"Authorization: Bearer <analytics-token>\" \\\n  \"https://trip.dev.2gether.dev.br/auth/analytics?eventKind=LOGIN&granularity=DAILY\""
          }
        ]
      }
    },
    "/classification": {
      "get": {
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "properties": {
                      "locale": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "uniqueId": {
                        "type": "string"
                      }
                    },
                    "type": "object",
                    "required": [
                      "locale",
                      "name",
                      "uniqueId"
                    ]
                  },
                  "type": "array",
                  "nullable": true
                },
                "example": [
                  {
                    "uniqueId": "group-example",
                    "name": "Training",
                    "locale": "PT"
                  }
                ]
              }
            },
            "description": "Dataset array; an empty result may be null."
          },
          "401": {
            "description": "Missing `Authorization` header (API Gateway responds `{\"message\":\"Unauthorized\"}`), or a valid token whose type is not `analytics`, such as an `authentication` token (example below).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                },
                "example": {
                  "name": "Unauthorized",
                  "message": "Authentication required",
                  "data": null
                }
              }
            }
          },
          "403": {
            "description": "The authorizer rejected the token: unknown, inactive, expired, or a denied type such as `mcp`."
          },
          "500": {
            "description": "Tenant configuration, token lookup, or data read failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Unable to read tenant data"
                }
              }
            }
          }
        },
        "description": "Returns tenant user-group IDs, labels, and locales. A successful empty result may be null.",
        "tags": [
          "Learning"
        ],
        "operationId": "queryUserGroups",
        "summary": "Query user classifications",
        "security": [
          {
            "TripToken": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl --fail-with-body \\\n  -H \"Authorization: Bearer <analytics-token>\" \\\n  \"https://trip.dev.2gether.dev.br/classification\""
          }
        ]
      }
    },
    "/content": {
      "get": {
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "properties": {
                      "contentId": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "groups": {
                        "items": {
                          "type": "string"
                        },
                        "type": "array",
                        "nullable": true
                      },
                      "locale": {
                        "type": "string"
                      },
                      "tags": {
                        "items": {
                          "type": "string"
                        },
                        "type": "array",
                        "nullable": true
                      },
                      "title": {
                        "type": "string"
                      },
                      "type": {
                        "type": "string"
                      }
                    },
                    "type": "object",
                    "required": [
                      "contentId",
                      "description",
                      "groups",
                      "locale",
                      "tags",
                      "title",
                      "type"
                    ]
                  },
                  "type": "array",
                  "nullable": true
                },
                "example": [
                  {
                    "contentId": "content-example",
                    "type": "JOURNEY",
                    "title": "Getting started",
                    "description": "Introductory learning journey",
                    "locale": "PT",
                    "tags": [
                      "onboarding"
                    ],
                    "groups": [
                      "group-example"
                    ]
                  }
                ]
              }
            },
            "description": "Dataset array; an empty result may be null."
          },
          "401": {
            "description": "Missing `Authorization` header (API Gateway responds `{\"message\":\"Unauthorized\"}`), or a valid token whose type is not `analytics`, such as an `authentication` token (example below).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                },
                "example": {
                  "name": "Unauthorized",
                  "message": "Authentication required",
                  "data": null
                }
              }
            }
          },
          "403": {
            "description": "The authorizer rejected the token: unknown, inactive, expired, or a denied type such as `mcp`."
          },
          "500": {
            "description": "Tenant configuration, token lookup, or data read failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Unable to read tenant data"
                }
              }
            }
          }
        },
        "description": "Returns visible JOURNEY and COLLECTION metadata from the authorized tenant. A successful empty result may be null.",
        "tags": [
          "Learning"
        ],
        "operationId": "queryContent",
        "summary": "Query learning content",
        "security": [
          {
            "TripToken": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl --fail-with-body \\\n  -H \"Authorization: Bearer <analytics-token>\" \\\n  \"https://trip.dev.2gether.dev.br/content\""
          }
        ]
      }
    },
    "/news": {
      "get": {
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "PT",
                "EN",
                "ES"
              ]
            },
            "description": "Required published News locale."
          },
          {
            "name": "onlyAvailable",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Use true or false, case-insensitive. True requires visibility; omitted means false. Empty values are invalid."
          },
          {
            "name": "includeArchived",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Use true or false, case-insensitive. True includes archived rows; omitted means false. Empty values are invalid."
          }
        ],
        "responses": {
          "200": {
            "description": "Dataset array; an empty result is [].",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "newsId": {
                        "type": "string"
                      },
                      "locale": {
                        "type": "string",
                        "enum": [
                          "PT",
                          "EN",
                          "ES"
                        ]
                      },
                      "title": {
                        "type": "string"
                      },
                      "shortDescription": {
                        "type": "string"
                      },
                      "longDescription": {
                        "type": "string"
                      },
                      "externalLink": {
                        "type": "string"
                      },
                      "deepLinks": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "groups": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "isVisible": {
                        "type": "boolean"
                      },
                      "isArchived": {
                        "type": "boolean"
                      },
                      "publishedAt": {
                        "type": "string",
                        "description": "Optional source field; published records may omit it."
                      },
                      "createdAt": {
                        "type": "string"
                      },
                      "lastEditAt": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "newsId",
                      "locale",
                      "title",
                      "shortDescription",
                      "longDescription",
                      "externalLink",
                      "deepLinks",
                      "groups",
                      "isVisible",
                      "isArchived",
                      "createdAt",
                      "lastEditAt"
                    ]
                  }
                },
                "example": [
                  {
                    "newsId": "news-example",
                    "locale": "PT",
                    "title": "News example",
                    "shortDescription": "Short description",
                    "longDescription": "Long description",
                    "externalLink": "",
                    "deepLinks": [],
                    "groups": [],
                    "isVisible": true,
                    "isArchived": false,
                    "createdAt": "2026-09-30T12:00:00Z",
                    "lastEditAt": "2026-09-30T12:00:00Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Required parameter missing, invalid enum/boolean, or invalid paired RFC3339 bounds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Invalid query parameter"
                }
              }
            }
          },
          "401": {
            "description": "Missing `Authorization` header (API Gateway responds `{\"message\":\"Unauthorized\"}`), or a valid token whose type is not `analytics`, such as an `authentication` token (example below).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Authentication required"
                }
              }
            }
          },
          "403": {
            "description": "The authorizer rejected the token: unknown, inactive, expired, or a denied type such as `mcp`."
          },
          "500": {
            "description": "Tenant configuration, token lookup, or data read failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Unable to read tenant data"
                }
              }
            }
          }
        },
        "description": "Enum values are case-insensitive and trimmed. Follows every page of the selected locale partition in descending News ID order. Hidden published rows are included by default; archives are excluded by default. Drafts, image enrichment, author identities, and internal storage keys are excluded.",
        "tags": [
          "News"
        ],
        "operationId": "queryNews",
        "summary": "Query published News",
        "security": [
          {
            "TripToken": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl --fail-with-body \\\n  -H \"Authorization: Bearer <analytics-token>\" \\\n  \"https://trip.dev.2gether.dev.br/news?locale=PT&onlyAvailable=true\""
          }
        ]
      }
    },
    "/news/analytics": {
      "get": {
        "parameters": [
          {
            "name": "newsId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "description": "Required News ID; trimmed but case preserved."
          },
          {
            "name": "grain",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "HOUR",
                "DAY",
                "WEEK",
                "MONTH"
              ]
            },
            "description": "Required time grain."
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Inclusive range start. RFC3339; must be paired with end. Example: 2026-09-01T00:00:00Z."
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Exclusive range end. RFC3339; must be paired with start and later than start. Example: 2026-10-01T00:00:00Z."
          }
        ],
        "responses": {
          "200": {
            "description": "Dataset array; an empty result is [].",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "newsId": {
                        "type": "string"
                      },
                      "grain": {
                        "type": "string",
                        "enum": [
                          "HOUR",
                          "DAY",
                          "WEEK",
                          "MONTH"
                        ]
                      },
                      "periodStart": {
                        "type": "string",
                        "description": "UTC hour YYYY-MM-DDTHH, day YYYY-MM-DD, ISO week YYYY-Www, or month YYYY-MM; grain prefix is omitted."
                      },
                      "openCount": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Recorded opens, including repeat opens."
                      }
                    },
                    "required": [
                      "newsId",
                      "grain",
                      "periodStart",
                      "openCount"
                    ]
                  }
                },
                "example": [
                  {
                    "newsId": "news-example",
                    "grain": "DAY",
                    "periodStart": "2026-09-30",
                    "openCount": 12
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Required parameter missing, invalid enum/boolean, or invalid paired RFC3339 bounds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Invalid query parameter"
                }
              }
            }
          },
          "401": {
            "description": "Missing `Authorization` header (API Gateway responds `{\"message\":\"Unauthorized\"}`), or a valid token whose type is not `analytics`, such as an `authentication` token (example below).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Authentication required"
                }
              }
            }
          },
          "403": {
            "description": "The authorizer rejected the token: unknown, inactive, expired, or a denied type such as `mcp`."
          },
          "500": {
            "description": "Tenant configuration, token lookup, or data read failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Unable to read tenant data"
                }
              }
            }
          }
        },
        "description": "Enum values are case-insensitive and trimmed. Returns ascending stored period buckets for one News item and grain, including archived IDs without a metadata lookup. No zero-fill or combined-grain totals are fabricated. Omit both bounds for all stored periods; otherwise provide both RFC3339 bounds with start < end. Bounds are converted to UTC and return periods overlapping [start, end), so counts cover full overlapping buckets. Empty bounds and `0001-01-01T00:00:00Z` are invalid.",
        "tags": [
          "News"
        ],
        "operationId": "queryNewsAnalytics",
        "summary": "Query News open counts",
        "security": [
          {
            "TripToken": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl --fail-with-body \\\n  -H \"Authorization: Bearer <analytics-token>\" \\\n  \"https://trip.dev.2gether.dev.br/news/analytics?newsId=news-example&grain=DAY&start=2026-09-01T00%3A00%3A00Z&end=2026-10-01T00%3A00%3A00Z\""
          }
        ]
      }
    },
    "/profiles": {
      "get": {
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "properties": {
                      "customInformation": {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      "groups": {
                        "items": {
                          "type": "string"
                        },
                        "type": "array",
                        "nullable": true
                      },
                      "userId": {
                        "type": "string"
                      },
                      "userName": {
                        "type": "string"
                      }
                    },
                    "type": "object",
                    "required": [
                      "groups",
                      "userId",
                      "userName"
                    ]
                  },
                  "type": "array",
                  "nullable": true
                },
                "example": [
                  {
                    "userId": "user-example",
                    "userName": "Example User",
                    "groups": [
                      "group-example"
                    ],
                    "customInformation": {
                      "department": "Training"
                    }
                  }
                ]
              }
            },
            "description": "Dataset array; an empty result may be null."
          },
          "401": {
            "description": "Missing `Authorization` header (API Gateway responds `{\"message\":\"Unauthorized\"}`), or a valid token whose type is not `analytics`, such as an `authentication` token (example below).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                },
                "example": {
                  "name": "Unauthorized",
                  "message": "Authentication required",
                  "data": null
                }
              }
            }
          },
          "403": {
            "description": "The authorizer rejected the token: unknown, inactive, expired, or a denied type such as `mcp`."
          },
          "500": {
            "description": "Tenant configuration, token lookup, or data read failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Unable to read tenant data"
                }
              }
            }
          }
        },
        "description": "Returns tenant user identifiers, names, groups, and optional custom information. A successful empty result may be null.",
        "tags": [
          "Users"
        ],
        "operationId": "queryProfiles",
        "summary": "Query user profiles",
        "security": [
          {
            "TripToken": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl --fail-with-body \\\n  -H \"Authorization: Bearer <analytics-token>\" \\\n  \"https://trip.dev.2gether.dev.br/profiles\""
          }
        ]
      }
    },
    "/progress": {
      "get": {
        "parameters": [
          {
            "name": "contentId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "description": "Learning content ID."
          },
          {
            "name": "contentType",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "JOURNEY",
                "COLLECTION"
              ]
            },
            "description": "Content type; case-insensitive."
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "properties": {
                      "completedAt": {
                        "type": "string"
                      },
                      "contentId": {
                        "type": "string"
                      },
                      "isCollected": {
                        "type": "boolean"
                      },
                      "points": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Recorded points."
                      },
                      "progress": {
                        "items": {
                          "type": "string"
                        },
                        "type": "array",
                        "nullable": true
                      },
                      "subscribedAt": {
                        "type": "string"
                      },
                      "userId": {
                        "type": "string"
                      }
                    },
                    "type": "object",
                    "required": [
                      "completedAt",
                      "contentId",
                      "isCollected",
                      "points",
                      "progress",
                      "subscribedAt",
                      "userId"
                    ]
                  },
                  "type": "array",
                  "nullable": true
                },
                "example": [
                  {
                    "userId": "user-example",
                    "contentId": "content-example",
                    "progress": [
                      "step-example"
                    ],
                    "subscribedAt": "2026-09-01T09:00:00Z",
                    "completedAt": "",
                    "isCollected": false,
                    "points": 10
                  }
                ]
              }
            },
            "description": "Dataset array; an empty result may be null."
          },
          "400": {
            "description": "Missing contentId/contentType, invalid encoding, or unsupported contentType. The invalid contentType branch preserves its legacy wrapped error.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DirectError"
                    },
                    {
                      "$ref": "#/components/schemas/LegacyError"
                    }
                  ]
                },
                "examples": {
                  "missing": {
                    "value": {
                      "message": "Missing query parameter: contentId"
                    }
                  },
                  "invalidType": {
                    "value": {
                      "name": "BadRequest",
                      "message": "Invalid query parameter: contentType",
                      "data": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing `Authorization` header (API Gateway responds `{\"message\":\"Unauthorized\"}`), or a valid token whose type is not `analytics`, such as an `authentication` token (example below).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                },
                "example": {
                  "name": "Unauthorized",
                  "message": "Authentication required",
                  "data": null
                }
              }
            }
          },
          "403": {
            "description": "The authorizer rejected the token: unknown, inactive, expired, or a denied type such as `mcp`."
          },
          "500": {
            "description": "Tenant configuration, token lookup, or data read failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DirectError"
                },
                "example": {
                  "message": "Unable to read tenant data"
                }
              }
            }
          }
        },
        "description": "Returns recorded user progress for one JOURNEY or COLLECTION ID. A successful empty result may be null.",
        "tags": [
          "Learning"
        ],
        "operationId": "queryProgress",
        "summary": "Query learning progress",
        "security": [
          {
            "TripToken": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl --fail-with-body \\\n  -H \"Authorization: Bearer <analytics-token>\" \\\n  \"https://trip.dev.2gether.dev.br/progress?contentId=content-example&contentType=JOURNEY\""
          }
        ]
      }
    }
  },
  "servers": [
    {
      "url": "https://trip.2gether.dev.br",
      "description": "Production"
    },
    {
      "url": "https://trip.dev.2gether.dev.br",
      "description": "Development"
    }
  ],
  "components": {
    "securitySchemes": {
      "TripToken": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Analytics API token, sent as `Bearer <token>` or as the raw token. The token's project selects the tenant."
      }
    },
    "schemas": {
      "DirectError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "description": "Error explanation."
          }
        }
      },
      "LegacyError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "message",
          "data"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "data": {
            "nullable": true,
            "description": "Legacy envelope data; normally null on an error."
          }
        }
      }
    }
  },
  "security": [
    {
      "TripToken": []
    }
  ],
  "tags": [
    {
      "name": "Users",
      "description": "User profile and account-access records for the authorized tenant."
    },
    {
      "name": "Learning",
      "description": "Visible learning content, user classifications, and recorded progress."
    },
    {
      "name": "Auth analytics",
      "description": "Recorded tenant LOGIN/REGISTER aggregates. No individual auth subjects or global series."
    },
    {
      "name": "News",
      "description": "Published News metadata and repeat-open period counts."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Tenant data",
      "tags": [
        "Users",
        "Learning"
      ]
    },
    {
      "name": "Analytics and communication",
      "tags": [
        "Auth analytics",
        "News"
      ]
    }
  ]
}
