Dropto Account API
The account a site belongs to, the people who can reach it, and the invitations that add them. An account is the unit everything else hangs from — sites, quota and billing are all per account rather than per person.
The account a site belongs to, the people who can reach it, and the invitations that add them. An account is the unit everything else hangs from — sites, quota and billing are all per account rather than per person.
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/dropto-run:dropto-run-account-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: Drop2Run.Api | v1 Account API
version: 1.0.0
description: The account a site belongs to, the people who can reach it, and the invitations that add them. An account is the unit everything else hangs from — sites, quota and billing are all per account rather than per person.
servers:
- description: Production
url: https://dropto.run
tags:
- description: The account a site belongs to, the people who can reach it, and the invitations that add them. An account is the unit everything else hangs from — sites, quota and billing are all per account rather than per person.
name: Account
paths:
/api/account:
patch:
operationId: RenameAccount
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/RenameAccountRequest'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/AccountResponse'
description: OK
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
security:
- session: []
- accessToken: []
summary: Renames the account being acted on
tags:
- Account
/api/account/invites:
post:
operationId: InviteAccountMember
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InviteMemberRequest'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/InviteResponse'
description: OK
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
'409':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Conflict
'429':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Too Many Requests
security:
- session: []
- accessToken: []
summary: Invites somebody onto the account and returns the link once
tags:
- Account
/api/account/invites/{inviteId}:
delete:
operationId: RevokeAccountInvite
parameters:
- in: path
name: inviteId
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/RemovedResponse'
description: OK
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
security:
- session: []
- accessToken: []
summary: Withdraws an invitation that has not been accepted
tags:
- Account
/api/account/members:
get:
operationId: ListAccountMembers
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/MembersResponse'
description: OK
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
security:
- session: []
- accessToken: []
summary: Lists who is on the account and which invitations still stand
tags:
- Account
/api/account/members/{userId}:
delete:
operationId: RemoveAccountMember
parameters:
- in: path
name: userId
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/RemovedResponse'
description: OK
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
'409':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Conflict
security:
- session: []
- accessToken: []
summary: Takes somebody off the account, effective on their next request
tags:
- Account
patch:
operationId: ChangeAccountMemberRole
parameters:
- in: path
name: userId
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ChangeRoleRequest'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/MemberRow'
description: OK
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
'409':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Conflict
security:
- session: []
- accessToken: []
summary: Changes what somebody on the account may do
tags:
- Account
/api/account/security:
patch:
description: Members without two-factor are refused from their next request. Access tokens they already made keep working.
operationId: SetAccountSecurity
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/SetAccountSecurityRequest'
description: Cancellation token.
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/AccountSecurityResponse'
description: OK
'400':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Bad Request
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
security:
- session: []
- accessToken: []
summary: Starts or stops requiring two-factor
tags:
- Account
/api/accounts:
get:
operationId: ListAccounts
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/AccountsResponse'
description: OK
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
security:
- session: []
- accessToken: []
summary: Lists the accounts the signed-in person may act on
tags:
- Account
/api/invites/accept:
post:
operationId: AcceptAccountInvite
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/AcceptInviteRequest'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/AcceptInviteResponse'
description: OK
'403':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Forbidden
'404':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Not Found
'409':
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
description: Conflict
security:
- session: []
- accessToken: []
summary: Joins the account an invitation link names
tags:
- Account
components:
schemas:
AccountSecurityResponse:
description: Response of `PATCH /account/security`.
properties:
requireTwoFactorAt:
description: Since when two-factor is required, or null while it is not.
format: date-time
type:
- 'null'
- string
required:
- requireTwoFactorAt
type: object
RemovedResponse:
description: What was taken away.
properties:
id:
description: The user or invitation that is gone.
type: string
required:
- id
type: object
ProblemDetails:
properties:
detail:
type:
- 'null'
- string
instance:
type:
- 'null'
- string
status:
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- 'null'
- integer
- string
title:
type:
- 'null'
- string
type:
type:
- 'null'
- string
type: object
AccountsResponse:
description: Response of `GET /api/accounts`.
properties:
accounts:
description: 'Every account the caller may act on, oldest membership first. Never empty for a signed-in person:
signing in creates an account for them, and they are its owner.'
items:
$ref: '#/components/schemas/AccountSummary'
type: array
required:
- accounts
type: object
MembersResponse:
description: Who is on the account, and who has been asked.
properties:
invites:
description: Invitations still standing. Spent and withdrawn ones are history, not a list.
items:
$ref: '#/components/schemas/InviteRow'
type: array
members:
description: People who may act on it, oldest first.
items:
$ref: '#/components/schemas/MemberRow'
type: array
requireTwoFactorAt:
description: Since when the owner has required two-factor of every member, or null while they have not.
format: date-time
type:
- 'null'
- string
tokensOfUnprotectedMembers:
description: 'Access tokens on this account held by members without two-factor. Requiring two-factor does not stop
them, so the owner is told before turning it on.'
format: int32
pattern: ^-?(?:0|[1-9]\d*)$
type:
- integer
- string
required:
- members
- invites
- requireTwoFactorAt
- tokensOfUnprotectedMembers
type: object
SetAccountSecurityRequest:
description: Body of `PATCH /account/security`.
properties:
requireTwoFactor:
description: Whether every member must sign in with two-factor.
type: boolean
required:
- requireTwoFactor
type: object
AccountResponse:
description: The account itself, as its members see it.
properties:
accountId:
description: Its ULID.
type: string
kind:
description: Whether it belongs to one person or is shared.
type: string
name:
description: What it calls itself, or null when nobody has named it.
type:
- 'null'
- string
required:
- accountId
- name
- kind
type: object
InviteResponse:
description: An invitation, as its sender sees it once.
properties:
acceptUrl:
description: 'The link. Returned here and nowhere else — only its hash is stored, so this response is the one
chance to copy it, which is what lets an owner pass it on when mail does not arrive.'
type: string
email:
description: The address it was sent to.
type: string
expiresAt:
description: When it stops working.
format: date-time
type: string
id:
description: Its id, for revoking.
type: string
required:
- id
- email
- acceptUrl
- expiresAt
type: object
RenameAccountRequest:
description: Body of `PATCH /account`.
properties:
name:
description: What to call the account, or null to clear the name.
maxLength: 255
type:
- 'null'
- string
required:
- name
type: object
ChangeRoleRequest:
description: Body of `PATCH /account/members/{userId}`.
properties:
role:
description: 'The role to give them: `Owner` or `Member`.'
maxLength: 16
type: string
required:
- role
type: object
AcceptInviteResponse:
description: What the accepter joined.
properties:
accountId:
description: The account they are now a member of.
type: string
accountName:
description: What it calls itself, or null when nobody has named it.
type:
- 'null'
- string
requiresTwoFactor:
description: 'Whether the account joined requires two-factor, so the page can say so before the gate does
(IMPLEMENTATION-PLAN §5.3.6).'
type: boolean
role:
description: What they may do there.
type: string
required:
- accountId
- accountName
- role
- requiresTwoFactor
type: object
InviteRow:
description: One invitation nobody has accepted yet.
properties:
email:
description: The address it was sent to. The link only works for this one.
type: string
expiresAt:
description: When it stops working on its own.
format: date-time
type: string
id:
description: Its id, which is what withdrawing it names.
type: string
role:
description: What accepting it would grant.
type: string
required:
- id
- email
- role
- expiresAt
type: object
InviteMemberRequest:
description: Body of `POST /account/invites`.
properties:
email:
description: Address to invite. Compared against the accepter's own before they are let in.
maxLength: 320
type: string
role:
description: 'What accepting grants: `Owner` or `Member`. Absent means member.
Absent rather than required, and defaulting to the lesser of the two, because an omitted field must
not hand out authority nobody asked for — the same rule every capability column on a plan follows.'
maxLength: 16
type:
- 'null'
- string
required:
- email
type: object
MemberRow:
description: One person on the account.
properties:
email:
description: Their address, which is how a colleague recognises them.
type: string
founder:
description: 'Whether they created the account. A founder cannot be removed or demoted while the plan is held in their
name, so the members screen offers neither for this row.'
type: boolean
joinedAt:
description: When they were added.
format: date-time
type: string
name:
description: Their display name, or null when Google gave none.
type:
- 'null'
- string
role:
description: What they may do here.
type: string
twoFactor:
description: 'Whether they have two-factor on — the column an owner reads before requiring it, and a member reads to
see whether the rule would block them.'
type: boolean
userId:
description: Their ULID, which is what removing them names.
type: string
required:
- userId
- email
- name
- role
- joinedAt
- twoFactor
- founder
type: object
AccountSummary:
description: One account, as the switcher lists it.
properties:
accountId:
description: What the account header carries to act on it.
type: string
kind:
description: Personal or Team, which is what the switcher labels the entry with.
type: string
name:
description: What it is called, or null for a personal account nobody has named.
type:
- 'null'
- string
role:
description: What the caller may do there. The same string `/me` reports for the current one.
type: string
stopped:
description: Whether the account has been stopped, directly or through one of its owners.
type: boolean
required:
- accountId
- name
- kind
- role
- stopped
type: object
AcceptInviteRequest:
description: Body of `POST /account/invites/accept`.
properties:
token:
description: The token from the invitation link.
maxLength: 200
type: string
required:
- token
type: object
securitySchemes:
accessToken:
description: 'A personal access token, created at /account/tokens. Sent as `Authorization: Bearer d2r_...`. A rejected token answers 401 with `invalid_token`, which is deliberately distinct from the 403 a valid credential gets for something it may not do.'
scheme: bearer
type: http
claimToken:
description: Returned once when an anonymous site is created, and the only credential that site has until somebody signs in and claims it.
in: header
name: X-Claim-Token
type: apiKey
session:
description: The browser session, set by signing in with Google. HttpOnly, so a script cannot read it and a client outside a browser cannot send it.
in: cookie
name: d2r_session
type: apiKey