esyURL Groups API
The groups API from esyURL — 5 operation(s) for groups.
The groups API from esyURL — 5 operation(s) for groups.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/esyurl-fyi:esyurl-fyi-groups-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Esyurl Fyi Groups API
version: 2.0.0
contact:
name: esyURL
email: contact@esyurl.fyi
url: https://esyurl.fyi/about/contact
x-guidance: 'Get an API key first: follow /auth.md (agents sign themselves up, no human needed). Then POST /v1/links with {"targetUrl": "...", "slug": "..."} for a short link and GET /v1/links/{id}/qr for its QR code. PUT /v1/domain {"domain": "go.example.com"} sets a custom domain; for self-signed-up tenants it answers 402 and is paid with x402 (USDC), once per domain. The full guide is /llms.txt.'
description: 'Operations tagged groups across 2 of this provider''s published API definitions: openapi.json, esyurl-fyi-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://esyurl.fyi
security:
- bearerAuth: []
- apiKeyHeader: []
tags:
- name: Groups
paths:
/v1/groups:
post:
tags:
- Groups
summary: Create a group
description: Requires `links:write`.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateGroup'
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/LinkGroup'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
WWW-Authenticate:
schema:
type: string
description: 'Bearer resource_metadata="{baseUrl}/.well-known/oauth-protected-resource" (RFC 9728; how to sign up: /auth.md)'
'403':
description: API key lacks the required scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: postV1Groups
x-operation-id-source: derived
get:
tags:
- Groups
summary: List groups, ordered by groupId
parameters:
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: cursor
in: query
schema:
type: string
description: '`nextCursor` from the previous page'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required:
- items
properties:
items:
type: array
items:
$ref: '#/components/schemas/LinkGroup'
nextCursor:
type: string
description: Pass back as `cursor`; absent on the last page
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
WWW-Authenticate:
schema:
type: string
description: 'Bearer resource_metadata="{baseUrl}/.well-known/oauth-protected-resource" (RFC 9728; how to sign up: /auth.md)'
'403':
description: API key lacks the required scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: getV1Groups
x-operation-id-source: derived
servers:
- url: https://esyurl.fyi
/v1/groups/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
description: groupId
get:
tags:
- Groups
summary: Get a group
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/LinkGroup'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
WWW-Authenticate:
schema:
type: string
description: 'Bearer resource_metadata="{baseUrl}/.well-known/oauth-protected-resource" (RFC 9728; how to sign up: /auth.md)'
'403':
description: API key lacks the required scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found (or not yours)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: getV1GroupsById
x-operation-id-source: derived
patch:
tags:
- Groups
summary: Rename a group or change its description/color
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateGroup'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/LinkGroup'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
WWW-Authenticate:
schema:
type: string
description: 'Bearer resource_metadata="{baseUrl}/.well-known/oauth-protected-resource" (RFC 9728; how to sign up: /auth.md)'
'403':
description: API key lacks the required scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found (or not yours)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: patchV1GroupsById
x-operation-id-source: derived
delete:
tags:
- Groups
summary: Delete a group; its links are kept, only the memberships go
responses:
'204':
description: Deleted
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
WWW-Authenticate:
schema:
type: string
description: 'Bearer resource_metadata="{baseUrl}/.well-known/oauth-protected-resource" (RFC 9728; how to sign up: /auth.md)'
'403':
description: API key lacks the required scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found (or not yours)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Concurrent change; retry
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: deleteV1GroupsById
x-operation-id-source: derived
servers:
- url: https://esyurl.fyi
/v1/groups/{id}/links:
parameters:
- name: id
in: path
required: true
schema:
type: string
description: groupId
get:
tags:
- Groups
summary: Links in the group, ordered by linkId
parameters:
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: cursor
in: query
schema:
type: string
description: '`nextCursor` from the previous page'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required:
- items
properties:
items:
type: array
items:
$ref: '#/components/schemas/ShortLink'
nextCursor:
type: string
description: Pass back as `cursor`; absent on the last page
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
WWW-Authenticate:
schema:
type: string
description: 'Bearer resource_metadata="{baseUrl}/.well-known/oauth-protected-resource" (RFC 9728; how to sign up: /auth.md)'
'403':
description: API key lacks the required scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found (or not yours)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: getV1GroupsByIdLinks
x-operation-id-source: derived
post:
tags:
- Groups
summary: Add links to the group (idempotent)
description: Up to 25 links per call. Links already in the group are reported in `alreadyMembers`. If any id is unknown, nothing is added (404). A link can be in at most 20 groups (400).
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AddGroupLinks'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/AddGroupLinksResult'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
WWW-Authenticate:
schema:
type: string
description: 'Bearer resource_metadata="{baseUrl}/.well-known/oauth-protected-resource" (RFC 9728; how to sign up: /auth.md)'
'403':
description: API key lacks the required scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found (or not yours)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Concurrent change; retry
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: postV1GroupsByIdLinks
x-operation-id-source: derived
servers:
- url: https://esyurl.fyi
/v1/groups/{id}/links/{linkId}:
delete:
tags:
- Groups
summary: Remove one link from the group
parameters:
- name: id
in: path
required: true
schema:
type: string
description: groupId
- name: linkId
in: path
required: true
schema:
type: string
responses:
'204':
description: Removed
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
WWW-Authenticate:
schema:
type: string
description: 'Bearer resource_metadata="{baseUrl}/.well-known/oauth-protected-resource" (RFC 9728; how to sign up: /auth.md)'
'403':
description: API key lacks the required scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Group not found, or link not in it
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: deleteV1GroupsByIdLinksByLinkId
x-operation-id-source: derived
servers:
- url: https://esyurl.fyi
/v1/groups/{id}/visits:
get:
tags:
- Groups
summary: Visits summed over the group's current member links
parameters:
- name: id
in: path
required: true
schema:
type: string
description: groupId
- name: days
in: query
schema:
type: integer
minimum: 1
maximum: 365
default: 30
description: UTC days back, including today
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/GroupVisits'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid API key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
WWW-Authenticate:
schema:
type: string
description: 'Bearer resource_metadata="{baseUrl}/.well-known/oauth-protected-resource" (RFC 9728; how to sign up: /auth.md)'
'403':
description: API key lacks the required scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found (or not yours)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
operationId: getV1GroupsByIdVisits
x-operation-id-source: derived
servers:
- url: https://esyurl.fyi
components:
schemas:
Error:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- bad_request
- validation_error
- unauthorized
- forbidden
- not_found
- conflict
- gone
- payment_required
- quota_exceeded
- rate_limited
- internal_error
- payments_not_configured
- service_unavailable
message:
type: string
details: {}
RuleCondition:
description: A test, or all/any/not of conditions (at most 4 deep, 20 tests per rule). See /llms.txt for the field/op table.
oneOf:
- type: object
required:
- field
- op
additionalProperties: false
properties:
field:
type: string
enum:
- os
- device
- browser
- language
- country
- referrer
- source
- query
- time
- weekday
- hour
op:
type: string
enum:
- eq
- neq
- in
- not_in
- contains
- starts_with
- ends_with
- exists
- before
- after
- gte
- lte
value:
oneOf:
- type: string
- type: number
- type: array
items:
oneOf:
- type: string
- type: number
description: Array for in/not_in; omitted for exists
key:
type: string
description: Query parameter name; only for field "query"
example:
field: os
op: eq
value: ios
- type: object
required:
- all
additionalProperties: false
properties:
all:
type: array
items:
$ref: '#/components/schemas/RuleCondition'
- type: object
required:
- any
additionalProperties: false
properties:
any:
type: array
items:
$ref: '#/components/schemas/RuleCondition'
- type: object
required:
- not
additionalProperties: false
properties:
not:
$ref: '#/components/schemas/RuleCondition'
RedirectRule:
type: object
required:
- when
- targetUrl
additionalProperties: false
properties:
id:
type: string
pattern: ^[A-Za-z0-9_-]{1,32}$
description: Generated if omitted; keep it when editing (visit stats are keyed by it)
name:
type: string
maxLength: 100
enabled:
type: boolean
default: true
when:
$ref: '#/components/schemas/RuleCondition'
targetUrl:
type: string
format: uri
description: http(s) only
Slug:
type: string
pattern: ^[a-zA-Z0-9_-]{3,64}$
description: Globally unique and immutable. Route names (health, v1, mcp, r, api, admin, www, ...) are reserved.
LinkGroup:
type: object
required:
- groupId
- tenantId
- name
- linkCount
- createdAt
- updatedAt
properties:
groupId:
type: string
tenantId:
type: string
name:
type: string
description:
type: string
color:
$ref: '#/components/schemas/HexColour'
linkCount:
type: integer
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
LinkPage:
type: object
description: 'A link page as stored: pictures are {imageId}, every item has its id, linkId items carry the slug they open.'
properties:
title:
type: string
bio:
type: string
avatar:
type: object
properties:
imageId:
type: string
items:
type: array
items:
type: object
socials:
type: array
items:
type: object
theme:
type: object
language:
type: string
noindex:
type: boolean
footer:
type: boolean
AddGroupLinksResult:
type: object
required:
- group
- added
- alreadyMembers
properties:
group:
$ref: '#/components/schemas/LinkGroup'
added:
type: array
items:
type: string
alreadyMembers:
type: array
items:
type: string
GroupIds:
type: array
maxItems: 20
uniqueItems: true
items:
$ref: '#/components/schemas/Id'
description: 'A set: returned sorted; duplicates are dropped'
GroupVisits:
type: object
required:
- groupId
- linkCount
- days
- totals
- daily
properties:
groupId:
type: string
linkCount:
type: integer
days:
type: integer
totals:
$ref: '#/components/schemas/VisitCounts'
daily:
type: array
items:
$ref: '#/components/schemas/DailyVisits'
CreateGroup:
type: object
required:
- name
additionalProperties: false
properties:
name:
type: string
minLength: 1
maxLength: 100
description:
type: string
maxLength: 500
color:
$ref: '#/components/schemas/HexColour'
DailyVisits:
allOf:
- $ref: '#/components/schemas/VisitCounts'
- type: object
required:
- date
properties:
date:
type: string
format: date
byRule:
type: object
additionalProperties:
type: integer
description: Human visits per rule id; only on days a rule matched (link visits only)
clicks:
type: object
additionalProperties:
type: integer
description: Human clicks per link page item id; only on days with clicks (link visits only)
HexColour:
type: string
pattern: ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$
examples:
- '#000000'
Id:
type: string
pattern: ^[A-Za-z0-9]{1,64}$
ShortLink:
type: object
required:
- linkId
- tenantId
- slug
- shortUrl
- tags
- metadata
- groupIds
- qrStyle
- status
- visitCount
- createdAt
- updatedAt
properties:
linkId:
type: string
tenantId:
type: string
slug:
$ref: '#/components/schemas/Slug'
targetUrl:
type: string
format: uri
description: Absent on link pages
page:
$ref: '#/components/schemas/LinkPage'
pageFooterPaid:
type: object
properties:
paymentKey:
type: string
at:
type: string
format: date-time
description: The page footer was paid off, for this link for good
warnings:
type: array
description: 'Create/update only: what reads badly on the page (low contrast, suspicious wording). The page was saved.'
items:
type: object
properties:
code:
type: string
enum:
- low_contrast
- suspicious_wording
path:
type: string
message:
type: string
ratio:
type: number
shortUrl:
type: string
format: uri
description: '`{base}/{slug}`; share this. QR images encode it with `?s=qr`.'
name:
type: string
tags:
$ref: '#/components/schemas/Tags'
metadata:
$ref: '#/components/schemas/Metadata'
groupIds:
$ref: '#/components/schemas/GroupIds'
qrStyle:
$ref: '#/components/schemas/QrStyle'
rules:
type: array
items:
$ref: '#/components/schemas/RedirectRule'
description: Evaluated in order on each visit; first match wins, else targetUrl. [] on links without rules
status:
type: string
enum:
- active
- paused
visitCount:
type: integer
description: Lifetime human visits (qr + direct); bots excluded
lastVisitedAt:
type: string
format: date-time
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
Metadata:
type: object
maxProperties: 20
additionalProperties:
type: string
maxLength: 512
VisitCounts:
type: object
required:
- visits
- qr
- direct
- bot
properties:
visits:
type: integer
description: 'Human visits: qr + direct'
qr:
type: integer
direct:
type: integer
bot:
type: integer
description: Link-preview fetchers and crawlers; not part of visits
QrStyle:
type: object
additionalProperties: false
description: How the link's QR image looks (free). Styled codes (any of modules, eyeFrame, eyeBall, eyeColor, image) need dark on light at a contrast of at least 3:1. In requests, `image` carries a new picture as `data`, or keeps the current one by its `imageId`; responses carry `imageId`.
properties:
dark:
$ref: '#/components/schemas/HexColour'
light:
$ref: '#/components/schemas/HexColour'
errorCorrectionLevel:
type: string
enum:
- L
- M
- Q
- H
description: Forced to H with a picture
margin:
type: integer
minimum: 0
maximum: 16
modules:
type: string
enum:
- square
- rounded
- dot
- row
- column
description: Shape of the data modules (default square)
eyeFrame:
type: string
enum:
- square
- rounded
- circle
description: Outer ring of the three corner markers
eyeBall:
type: string
enum:
- square
- rounded
- circle
description: Centre of the corner markers
eyeColor:
$ref: '#/components/schemas/HexColour'
description: Colour of the corner markers; defaults to dark
image:
type: object
required:
- mode
additionalProperties: false
properties:
mode:
type: string
enum:
- logo
- halftone
description: 'logo: in the middle; halftone: a photo behind the code, drawn as dots'
data:
type: string
description: data:image/png;base64,... (png, jpeg, webp or gif, up to 2 MB)
imageId:
type: string
description: The stored picture; send it back to keep it
size:
type: number
minimum: 0.1
maximum: 0.3
description: Logo side as a share of the code (default 0.22)
UpdateGroup:
type: object
minProperties: 1
additionalProperties: false
properties:
name:
type: string
minLength: 1
maxLength: 100
description:
type: string
maxLength: 500
color:
$ref: '#/components/schemas/HexColour'
AddGroupLinks:
type: object
required:
- linkIds
additionalProperties: false
properties:
linkIds:
type: array
minItems: 1
maxItems: 25
items:
$ref: '#/components/schemas/Id'
Tags:
type: array
maxItems: 20
items:
type: string
minLength: 1
maxLength: 64
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: API key `esy_{keyId}_{secret}`, from an operator or from agent self-sign-up (/auth.md)
apiKeyHeader:
type: apiKey
in: header
name: x-api-key
x-refined-from:
- openapi.json
- esyurl-fyi-openapi.json