Initial AS213905 SDK release
This commit is contained in:
@@ -0,0 +1,611 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: AS213905 API
|
||||
version: 1.1.0
|
||||
description: |
|
||||
Customer automation API for organisations, invoices, services, traffic,
|
||||
tunnels and RFC 8805 geofeeds. Create a scoped key in Panel → Settings.
|
||||
contact:
|
||||
name: AS213905 NOC
|
||||
email: noc@as213905.com
|
||||
url: https://as213905.com/docs/api
|
||||
license:
|
||||
name: Proprietary API; SDKs licensed under MIT
|
||||
url: https://git.datacoria.com/Phylex/as213905-sdk/src/branch/main/LICENSE
|
||||
servers:
|
||||
- url: https://as213905.com
|
||||
tags:
|
||||
- name: Organisation
|
||||
description: The organisation bound to the API key.
|
||||
- name: Invoices
|
||||
description: Billing documents and payment state.
|
||||
- name: Services
|
||||
description: Customer services, BGP VM metrics and power actions.
|
||||
- name: Traffic
|
||||
description: Organisation and per-tunnel traffic accounting.
|
||||
- name: Tunnels
|
||||
description: Transit tunnel inventory and lifecycle.
|
||||
- name: Geofeeds
|
||||
description: RFC 8805 public geofeed management.
|
||||
security:
|
||||
- apiKey: []
|
||||
paths:
|
||||
/api/v1/organization:
|
||||
get:
|
||||
tags: [Organisation]
|
||||
summary: Get the API key's organisation
|
||||
operationId: getOrganization
|
||||
x-required-scope: organizations:read
|
||||
responses:
|
||||
'200':
|
||||
description: Organisation
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/OrganizationResponse'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
/api/v1/invoices:
|
||||
get:
|
||||
tags: [Invoices]
|
||||
summary: List invoices, newest first
|
||||
operationId: listInvoices
|
||||
x-required-scope: invoices:read
|
||||
responses:
|
||||
'200':
|
||||
description: Invoice list
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [invoices]
|
||||
properties:
|
||||
invoices: {type: array, items: {$ref: '#/components/schemas/Invoice'}}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
/api/v1/services:
|
||||
get:
|
||||
tags: [Services]
|
||||
summary: List services
|
||||
operationId: listServices
|
||||
x-required-scope: services:read
|
||||
responses:
|
||||
'200':
|
||||
description: Service list
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [services]
|
||||
properties:
|
||||
services: {type: array, items: {$ref: '#/components/schemas/Service'}}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
/api/v1/services/{id}:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/ResourceId'}
|
||||
get:
|
||||
tags: [Services]
|
||||
summary: Get one service
|
||||
operationId: getService
|
||||
x-required-scope: services:read
|
||||
responses:
|
||||
'200':
|
||||
description: Service
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [service]
|
||||
properties:
|
||||
service: {$ref: '#/components/schemas/Service'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/api/v1/services/{id}/metrics:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/ResourceId'}
|
||||
get:
|
||||
tags: [Services]
|
||||
summary: Read a BGP VM metric series
|
||||
operationId: getServiceMetrics
|
||||
x-required-scope: services:read
|
||||
parameters:
|
||||
- name: target
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum: [cpu_load, mem_usage_percent, net_rx, net_tx, iops, df.root.used]
|
||||
default: cpu_load
|
||||
- name: range
|
||||
in: query
|
||||
schema: {type: string, enum: [1h, 6h, 24h, 7d], default: 24h}
|
||||
responses:
|
||||
'200':
|
||||
description: Metric series
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/MetricSeries'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/api/v1/services/{id}/power:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/ResourceId'}
|
||||
post:
|
||||
tags: [Services]
|
||||
summary: Start, stop or restart a BGP VM
|
||||
operationId: powerService
|
||||
x-required-scope: services:write
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [action]
|
||||
properties:
|
||||
action: {type: string, enum: [start, stop, restart]}
|
||||
responses:
|
||||
'202':
|
||||
description: Command accepted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [status, action]
|
||||
properties:
|
||||
status: {type: string, const: accepted}
|
||||
action: {type: string, enum: [start, stop, restart]}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
'429': {$ref: '#/components/responses/RateLimited'}
|
||||
/api/v1/traffic:
|
||||
get:
|
||||
tags: [Traffic]
|
||||
summary: Get organisation transit usage
|
||||
operationId: getTraffic
|
||||
x-required-scope: traffic:read
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/Days'}
|
||||
- {$ref: '#/components/parameters/From'}
|
||||
- {$ref: '#/components/parameters/To'}
|
||||
responses:
|
||||
'200':
|
||||
description: Traffic summary
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/Traffic'}
|
||||
'400': {$ref: '#/components/responses/BadRequest'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
/api/v1/tunnels:
|
||||
get:
|
||||
tags: [Tunnels]
|
||||
summary: List tunnels
|
||||
operationId: listTunnels
|
||||
x-required-scope: tunnels:read
|
||||
responses:
|
||||
'200':
|
||||
description: Tunnel list
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [tunnels]
|
||||
properties:
|
||||
tunnels: {type: array, items: {$ref: '#/components/schemas/Tunnel'}}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
post:
|
||||
tags: [Tunnels]
|
||||
summary: Request a transit tunnel
|
||||
operationId: createTunnel
|
||||
x-required-scope: tunnels:write
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/CreateTunnelRequest'}
|
||||
responses:
|
||||
'202':
|
||||
description: Tunnel recorded for provisioning
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [tunnel]
|
||||
properties:
|
||||
tunnel: {$ref: '#/components/schemas/Tunnel'}
|
||||
'400': {$ref: '#/components/responses/BadRequest'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
/api/v1/tunnels/{id}:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/ResourceId'}
|
||||
delete:
|
||||
tags: [Tunnels]
|
||||
summary: Remove a tunnel asynchronously
|
||||
operationId: deleteTunnel
|
||||
x-required-scope: tunnels:write
|
||||
responses:
|
||||
'202':
|
||||
description: Removal accepted
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/StatusResponse'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/api/v1/tunnels/{id}/traffic:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/ResourceId'}
|
||||
get:
|
||||
tags: [Traffic, Tunnels]
|
||||
summary: Get one tunnel's usage
|
||||
operationId: getTunnelTraffic
|
||||
x-required-scope: traffic:read
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/Days'}
|
||||
- {$ref: '#/components/parameters/From'}
|
||||
- {$ref: '#/components/parameters/To'}
|
||||
responses:
|
||||
'200':
|
||||
description: Tunnel traffic
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/TunnelTraffic'}
|
||||
'400': {$ref: '#/components/responses/BadRequest'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/api/v1/geofeeds:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/OrganizationId'}
|
||||
get:
|
||||
tags: [Geofeeds]
|
||||
summary: List geofeeds
|
||||
operationId: listGeofeeds
|
||||
x-required-scope: geofeeds:read
|
||||
responses:
|
||||
'200':
|
||||
description: Geofeed list
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/GeofeedList'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
post:
|
||||
tags: [Geofeeds]
|
||||
summary: Create a geofeed (maximum two per organisation)
|
||||
operationId: createGeofeed
|
||||
x-required-scope: geofeeds:write
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [name]
|
||||
properties:
|
||||
name: {type: string, minLength: 1, maxLength: 100}
|
||||
responses:
|
||||
'201':
|
||||
description: Created
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/GeofeedList'}
|
||||
'400': {$ref: '#/components/responses/BadRequest'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'409': {$ref: '#/components/responses/Conflict'}
|
||||
/api/v1/geofeeds/{id}:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/OrganizationId'}
|
||||
- {$ref: '#/components/parameters/ResourceId'}
|
||||
get:
|
||||
tags: [Geofeeds]
|
||||
summary: Get a geofeed and its records
|
||||
operationId: getGeofeed
|
||||
x-required-scope: geofeeds:read
|
||||
responses:
|
||||
'200':
|
||||
description: Geofeed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [geofeed]
|
||||
properties:
|
||||
geofeed: {$ref: '#/components/schemas/GeofeedWithRecords'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
patch:
|
||||
tags: [Geofeeds]
|
||||
summary: Rename a geofeed
|
||||
operationId: updateGeofeed
|
||||
x-required-scope: geofeeds:write
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [name]
|
||||
properties:
|
||||
name: {type: string, minLength: 1, maxLength: 100}
|
||||
responses:
|
||||
'200':
|
||||
description: Updated
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/StatusResponse'}
|
||||
'400': {$ref: '#/components/responses/BadRequest'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
delete:
|
||||
tags: [Geofeeds]
|
||||
summary: Delete a geofeed
|
||||
operationId: deleteGeofeed
|
||||
x-required-scope: geofeeds:write
|
||||
responses:
|
||||
'200':
|
||||
description: Deleted
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/StatusResponse'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/api/v1/geofeeds/{id}/records:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/OrganizationId'}
|
||||
- {$ref: '#/components/parameters/ResourceId'}
|
||||
put:
|
||||
tags: [Geofeeds]
|
||||
summary: Atomically replace all RFC 8805 records
|
||||
operationId: replaceGeofeedRecords
|
||||
x-required-scope: geofeeds:write
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [records]
|
||||
properties:
|
||||
records:
|
||||
type: array
|
||||
maxItems: 1000
|
||||
items: {$ref: '#/components/schemas/GeofeedRecordInput'}
|
||||
responses:
|
||||
'200':
|
||||
description: Saved
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/StatusResponse'}
|
||||
'400': {$ref: '#/components/responses/BadRequest'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/api/v1/geofeeds/{id}/rotate:
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/OrganizationId'}
|
||||
- {$ref: '#/components/parameters/ResourceId'}
|
||||
post:
|
||||
tags: [Geofeeds]
|
||||
summary: Rotate the unguessable public CSV URL
|
||||
operationId: rotateGeofeedUrl
|
||||
x-required-scope: geofeeds:write
|
||||
responses:
|
||||
'200':
|
||||
description: Rotated
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/GeofeedList'}
|
||||
'401': {$ref: '#/components/responses/Unauthenticated'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
components:
|
||||
securitySchemes:
|
||||
apiKey:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: as213905_…
|
||||
description: API key from Panel → Settings. Query-string keys are rejected.
|
||||
parameters:
|
||||
ResourceId:
|
||||
name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: {type: string, format: uuid}
|
||||
OrganizationId:
|
||||
name: X-Organization-ID
|
||||
in: header
|
||||
required: true
|
||||
description: Organisation UUID. An API key can only address its own organisation.
|
||||
schema: {type: string, format: uuid}
|
||||
Days:
|
||||
name: days
|
||||
in: query
|
||||
description: Last N days; mutually exclusive with from/to.
|
||||
schema: {type: integer, minimum: 1, maximum: 366}
|
||||
From:
|
||||
name: from
|
||||
in: query
|
||||
schema: {type: string, format: date}
|
||||
To:
|
||||
name: to
|
||||
in: query
|
||||
description: Inclusive whole-day end.
|
||||
schema: {type: string, format: date}
|
||||
responses:
|
||||
BadRequest:
|
||||
description: Invalid request
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/APIError'}}}
|
||||
Unauthenticated:
|
||||
description: Missing, malformed, expired, revoked or unknown API key
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/APIError'}}}
|
||||
Forbidden:
|
||||
description: Missing scope or disallowed source address
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/APIError'}}}
|
||||
NotFound:
|
||||
description: Resource not found
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/APIError'}}}
|
||||
Conflict:
|
||||
description: Resource limit or state conflict
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/APIError'}}}
|
||||
RateLimited:
|
||||
description: Rate limit exceeded
|
||||
headers:
|
||||
Retry-After: {schema: {type: integer}}
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/APIError'}}}
|
||||
schemas:
|
||||
APIError:
|
||||
type: object
|
||||
required: [error]
|
||||
properties:
|
||||
error: {type: string, examples: [scope_required]}
|
||||
message: {type: string}
|
||||
required_scope: {type: string}
|
||||
retry_after: {type: integer}
|
||||
StatusResponse:
|
||||
type: object
|
||||
required: [status]
|
||||
properties: {status: {type: string}}
|
||||
OrganizationResponse:
|
||||
type: object
|
||||
required: [organization]
|
||||
properties: {organization: {$ref: '#/components/schemas/Organization'}}
|
||||
Organization:
|
||||
type: object
|
||||
required: [id, asn, name, status, commit_kbps]
|
||||
properties:
|
||||
id: {type: string, format: uuid}
|
||||
asn: {type: integer, minimum: 1, maximum: 4294967295}
|
||||
name: {type: string}
|
||||
status: {type: string}
|
||||
commit_kbps: {type: integer, format: int64}
|
||||
Invoice:
|
||||
type: object
|
||||
required: [id, number, status, currency, total_cents]
|
||||
properties:
|
||||
id: {type: string, format: uuid}
|
||||
number: {type: string}
|
||||
status: {type: string, enum: [draft, issued, paid, overdue, cancelled]}
|
||||
currency: {type: string, minLength: 3, maxLength: 3}
|
||||
total_cents: {type: integer, format: int64}
|
||||
period_from: {type: [string, 'null'], format: date}
|
||||
period_to: {type: [string, 'null'], format: date}
|
||||
issued_at: {type: [string, 'null'], format: date-time}
|
||||
due_at: {type: [string, 'null'], format: date-time}
|
||||
Service:
|
||||
type: object
|
||||
required: [id, kind, label, status, monthly_cents]
|
||||
properties:
|
||||
id: {type: string, format: uuid}
|
||||
kind: {type: string}
|
||||
label: {type: string}
|
||||
status: {type: string, enum: [awaiting_payment, provisioning, active, suspended, terminating, terminated]}
|
||||
monthly_cents: {type: integer, format: int64}
|
||||
next_due_on: {type: [string, 'null'], format: date}
|
||||
controllable: {type: boolean}
|
||||
location: {type: string}
|
||||
configuration: {type: object, additionalProperties: true}
|
||||
MetricPoint:
|
||||
type: object
|
||||
required: [t]
|
||||
properties:
|
||||
t: {type: string, format: date-time}
|
||||
v: {type: number}
|
||||
MetricSeries:
|
||||
type: object
|
||||
required: [metric, target, range, points]
|
||||
properties:
|
||||
metric: {type: string}
|
||||
target: {type: string}
|
||||
range: {type: string}
|
||||
points: {type: array, items: {$ref: '#/components/schemas/MetricPoint'}}
|
||||
Period:
|
||||
type: object
|
||||
required: [from, to, label]
|
||||
properties:
|
||||
from: {type: string, format: date-time}
|
||||
to: {type: string, format: date-time}
|
||||
label: {type: string}
|
||||
Traffic:
|
||||
type: object
|
||||
required: [p95_kbps, total_bytes, total_gb, period]
|
||||
properties:
|
||||
p95_kbps: {type: integer, format: int64}
|
||||
commit_kbps: {type: integer, format: int64}
|
||||
over_commit: {type: boolean}
|
||||
total_bytes: {type: integer, format: int64}
|
||||
total_gb: {type: number}
|
||||
period: {$ref: '#/components/schemas/Period'}
|
||||
Tunnel:
|
||||
type: object
|
||||
required: [id, status, location, peer_endpoint]
|
||||
properties:
|
||||
id: {type: string, format: uuid}
|
||||
status: {type: string, enum: [provisioning, configuring, awaiting_peer, active, error, suspended, removed]}
|
||||
label: {type: string}
|
||||
location: {type: string, examples: [fra]}
|
||||
peer_endpoint: {type: string, format: ip}
|
||||
ifname: {type: string}
|
||||
inner_v4: {type: string}
|
||||
inner_v6: {type: string}
|
||||
announce: {type: boolean}
|
||||
CreateTunnelRequest:
|
||||
type: object
|
||||
required: [peer_endpoint, location]
|
||||
properties:
|
||||
peer_endpoint: {type: string, format: ip}
|
||||
location: {type: string, examples: [fra]}
|
||||
label: {type: string, maxLength: 100}
|
||||
announce: {type: boolean, default: false}
|
||||
TunnelTraffic:
|
||||
allOf:
|
||||
- {$ref: '#/components/schemas/Traffic'}
|
||||
- type: object
|
||||
required: [tunnel]
|
||||
properties: {tunnel: {$ref: '#/components/schemas/Tunnel'}}
|
||||
Geofeed:
|
||||
type: object
|
||||
required: [id, name, slug, record_count, created_at, updated_at]
|
||||
properties:
|
||||
id: {type: string, format: uuid}
|
||||
name: {type: string}
|
||||
slug: {type: string}
|
||||
record_count: {type: integer, minimum: 0}
|
||||
created_at: {type: string, format: date-time}
|
||||
updated_at: {type: string, format: date-time}
|
||||
GeofeedRecordInput:
|
||||
type: object
|
||||
required: [prefix, country_code]
|
||||
properties:
|
||||
prefix: {type: string, examples: [203.0.113.0/24]}
|
||||
country_code: {type: string, pattern: '^[A-Z]{2}$', examples: [DE]}
|
||||
region_code: {type: string, maxLength: 128, examples: [DE-HE]}
|
||||
city: {type: string, maxLength: 128, examples: [Frankfurt am Main]}
|
||||
postal_code: {type: string, maxLength: 128}
|
||||
GeofeedRecord:
|
||||
allOf:
|
||||
- {$ref: '#/components/schemas/GeofeedRecordInput'}
|
||||
- type: object
|
||||
properties: {id: {type: string, format: uuid}}
|
||||
GeofeedWithRecords:
|
||||
allOf:
|
||||
- {$ref: '#/components/schemas/Geofeed'}
|
||||
- type: object
|
||||
required: [records]
|
||||
properties:
|
||||
records: {type: array, items: {$ref: '#/components/schemas/GeofeedRecord'}}
|
||||
GeofeedList:
|
||||
type: object
|
||||
required: [geofeeds, limit]
|
||||
properties:
|
||||
geofeeds: {type: array, items: {$ref: '#/components/schemas/Geofeed'}}
|
||||
limit: {type: integer, const: 2}
|
||||
Reference in New Issue
Block a user