space.highport.manage.getSiteTraffic

lexicons.highport.space

Schema Diff

+4 -0

From

CID
bafyreigaa44snhd...
Indexed At
2026-09-07 12:02 UTC
View this version

To

CID
bafyreiebijv5ixk...
Indexed At
2026-09-12 02:53 UTC
View this version

Compatibility Analysis

Backward Compatible

Backward compatible. 2 non-breaking changes.

Non-Breaking Changes (2)
  • AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.buckets:items.botRequests" }
  • AddedEdge AddedEdge { src: "space.highport.manage.getSiteTraffic:output.buckets:items", tgt: "space.highport.manage.getSiteTraffic:output.buckets:items.botRequests", kind: "prop", name: Some("botRequests") }

Migration Guidance

Added Elements

  • AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.buckets:items.botRequests" }

Additional Notes

  • Non-breaking: AddedEdge { src: "space.highport.manage.getSiteTraffic:output.buckets:items", tgt: "space.highport.manage.getSiteTraffic:output.buckets:items.botRequests", kind: "prop", name: Some("botRequests") }
1 1
{
2 2
  "id": "space.highport.manage.getSiteTraffic",
3 3
  "defs": {
4 4
    "main": {
5 5
      "type": "query",
6 6
      "errors": [
7 7
        {
8 8
          "name": "InvalidDomain",
9 9
          "description": "Not a syntactically valid, non-reserved, public-suffix-safe domain. Distinct from DomainNotFound: the string is not a hostname at all."
10 10
        },
11 11
        {
12 12
          "name": "DomainNotFound",
13 13
          "description": "No such domain, or it is not registered to the calling identity. The two are one answer so the method is not an existence oracle."
14 14
        },
15 15
        {
16 16
          "name": "AnalyticsDisabled",
17 17
          "description": "This deployment has no analytics store configured, so no traffic was ever recorded."
18 18
        }
19 19
      ],
20 20
      "output": {
21 21
        "schema": {
22 22
          "type": "object",
23 23
          "required": [
24 24
            "domain",
25 25
            "bytesBilled",
26 26
            "bytesBilledToVisitors",
27 27
            "headerEstimateBytes",
28 28
            "buckets",
29 29
            "topPaths",
30 30
            "statuses"
31 31
          ],
32 32
          "properties": {
33 33
            "domain": {
34 34
              "type": "string"
35 35
            },
36 36
            "buckets": {
37 37
              "type": "array",
38 38
              "items": {
39 39
                "type": "object",
40 40
                "required": [
41 41
                  "bucket",
42 42
                  "requests",
43 43
                  "bytesBody",
44 44
                  "bytesBilled"
45 45
                ],
46 46
                "properties": {
47 47
                  "bucket": {
48 48
                    "type": "string",
49 49
                    "format": "datetime",
50 50
                    "description": "The hour this bucket starts."
51 51
                  },
52 52
                  "requests": {
53 53
                    "type": "integer",
54 54
                    "description": "Responses in the hour."
55 55
                  },
56 56
                  "bytesBody": {
57 57
                    "type": "integer",
58 58
                    "description": "Response body bytes, as the edge logged them."
59 59
                  },
60 +
                  "botRequests": {
61 +
                    "type": "integer",
62 +
                    "description": "How many of requests came from a client classified as a crawler, which is a subset of it and not a sibling. There is no byte-level equivalent: the bucket carries no client_class split of bytesBody or bytesBilled. Absent from a deployment that does not report the split, which a reader shows as no answer rather than as no crawlers."
63 +
                  },
60 64
                  "bytesBilled": {
61 65
                    "type": "integer",
62 66
                    "description": "Body bytes plus the per-response header estimate."
63 67
                  }
64 68
                },
65 69
                "description": "One hour of a domain's traffic."
66 70
              },
67 71
              "description": "Hourly buckets, oldest first."
68 72
            },
69 73
            "records": {
70 74
              "type": "array",
71 75
              "items": {
72 76
                "type": "object",
73 77
                "required": [
74 78
                  "recordCid",
75 79
                  "firstSeen",
76 80
                  "requests",
77 81
                  "bytesBilled"
78 82
                ],
79 83
                "properties": {
80 84
                  "lastSeen": {
81 85
                    "type": "string",
82 86
                    "format": "datetime",
83 87
                    "description": "The last, which with firstSeen is how long the version was serving inside the range — what makes one version's byte figure comparable to another's. Absent where the answer is not known, which a reader shows as still serving rather than as an interval it was not given."
84 88
                  },
85 89
                  "requests": {
86 90
                    "type": "integer",
87 91
                    "description": "Responses."
88 92
                  },
89 93
                  "firstSeen": {
90 94
                    "type": "string",
91 95
                    "format": "datetime",
92 96
                    "description": "The first response inside the range served from this version."
93 97
                  },
94 98
                  "recordCid": {
95 99
                    "type": "string",
96 100
                    "format": "cid",
97 101
                    "description": "The site record the serving snapshot was built from. Every response already names it, so the split needs nothing tagged."
98 102
                  },
99 103
                  "bytesBilled": {
100 104
                    "type": "integer",
101 105
                    "description": "Billed bytes."
102 106
                  }
103 107
                },
104 108
                "description": "One published version, and the traffic the snapshots built from it served."
105 109
              },
106 110
              "description": "Which published version of the site record served the traffic, heaviest first. Bounded by topRecords, so a domain republished more often than that has versions this does not list. Absent from a deployment that does not report the split."
107 111
            },
108 112
            "refusals": {
109 113
              "type": "object",
110 114
              "required": [
111 115
                "requests"
112 116
              ],
113 117
              "properties": {
114 118
                "requests": {
115 119
                  "type": "integer",
116 120
                  "description": "Responses refused because the payer's allowance for the period was spent. The same responses the status mix counts as 402, taken from the same read so the two figures cannot disagree."
117 121
                },
118 122
                "estimatedBytes": {
119 123
                  "type": "integer",
120 124
                  "description": "What serving those responses instead would have charged the owner. Absent unless the deployment records it: a refusal transferred no body, so its cost is in no logged size, and only the edge knows how large the path it refused would have been."
121 125
                }
122 126
              },
123 127
              "description": "What the bandwidth allowance refused over the range, and what serving it would have cost. Absent from a deployment that does not report it."
124 128
            },
125 129
            "statuses": {
126 130
              "type": "array",
127 131
              "items": {
128 132
                "type": "object",
129 133
                "required": [
130 134
                  "status",
131 135
                  "requests",
132 136
                  "bytesBilled",
133 137
                  "botRequests"
134 138
                ],
135 139
                "properties": {
136 140
                  "status": {
137 141
                    "type": "integer",
138 142
                    "description": "The HTTP status."
139 143
                  },
140 144
                  "requests": {
141 145
                    "type": "integer",
142 146
                    "description": "Responses with this status."
143 147
                  },
144 148
                  "botRequests": {
145 149
                    "type": "integer",
146 150
                    "description": "How many of those came from a client classified as a crawler. Crawler traffic is billed, because it is real egress and the alternative rewards user-agent spoofing."
147 151
                  },
148 152
                  "bytesBilled": {
149 153
                    "type": "integer",
150 154
                    "description": "Billed bytes."
151 155
                  }
152 156
                },
153 157
                "description": "One status code's share of the requests and of the bytes."
154 158
              },
155 159
              "description": "The status mix, with the crawler share alongside it."
156 160
            },
157 161
            "topPaths": {
158 162
              "type": "array",
159 163
              "items": {
160 164
                "type": "object",
161 165
                "required": [
162 166
                  "path",
163 167
                  "requests",
164 168
                  "bytesBilled"
165 169
                ],
166 170
                "properties": {
167 171
                  "path": {
168 172
                    "type": "string",
169 173
                    "description": "The request path."
170 174
                  },
171 175
                  "requests": {
172 176
                    "type": "integer",
173 177
                    "description": "Responses."
174 178
                  },
175 179
                  "bytesBilled": {
176 180
                    "type": "integer",
177 181
                    "description": "Billed bytes."
178 182
                  }
179 183
                },
180 184
                "description": "One path and what it cost."
181 185
              },
182 186
              "description": "The busiest paths over the range."
183 187
            },
184 188
            "bytesBilled": {
185 189
              "type": "integer",
186 190
              "description": "Total billed bytes over the range."
187 191
            },
188 192
            "headerEstimateBytes": {
189 193
              "type": "integer",
190 194
              "description": "The flat per-response constant added to every logged body size. Every byte figure here is an estimate by this much per response."
191 195
            },
192 196
            "bytesBilledToVisitors": {
193 197
              "type": "integer",
194 198
              "description": "How much of bytesBilled an authenticated visitor paid for rather than the owner. Zero unless the domain is on the sender-pays policy."
195 199
            }
196 200
          }
197 201
        },
198 202
        "encoding": "application/json"
199 203
      },
200 204
      "parameters": {
201 205
        "type": "params",
202 206
        "required": [
203 207
          "domain"
204 208
        ],
205 209
        "properties": {
206 210
          "to": {
207 211
            "type": "string",
208 212
            "format": "datetime",
209 213
            "description": "Exclusive upper bound. Defaults to now."
210 214
          },
211 215
          "from": {
212 216
            "type": "string",
213 217
            "format": "datetime",
214 218
            "description": "Inclusive lower bound. Defaults to 30 days ago."
215 219
          },
216 220
          "domain": {
217 221
            "type": "string",
218 222
            "maxLength": 253,
219 223
            "description": "The registered hostname. Must be registered to the calling identity."
220 224
          },
221 225
          "topPaths": {
222 226
            "type": "integer",
223 227
            "default": 20,
224 228
            "maximum": 100,
225 229
            "minimum": 0,
226 230
            "description": "How many of the busiest paths to return."
227 231
          },
228 232
          "topRecords": {
229 233
            "type": "integer",
230 234
            "default": 20,
231 235
            "maximum": 100,
232 236
            "minimum": 0,
233 237
            "description": "How many published record versions to return. A record CID is not a small set: a domain republished often has one per publish, so this is a top-N and not the whole history."
234 238
          }
235 239
        }
236 240
      },
237 241
      "description": "Traffic to one domain the caller owns, over a range: requests and bytes per hour, the busiest paths, and the status mix. Byte figures include a flat per-response header estimate, because the edge's access log records the response body only."
238 242
    }
239 243
  },
240 244
  "$type": "com.atproto.lexicon.schema",
241 245
  "lexicon": 1
242 246
}

Compare Other Versions

Lexicon Garden

@