All API requests need to be made using secure connections, i.e. with https
or
wss
protocols, and their paths should be prefixed by /api/
.
Some GET paths include query parameters. POST body parameters may be included
either as application/x-www-form-urlencoded
or as application/json
. All
server responses will be formatted as JSON.
In cases of error, the HTTP status code will be 400
or 401
for client error,
and 500
for server error. The response should contain a status
field with
the contents "error"
or "unauthorized"
, as appropriate, possibly along with
some relevant data and/or a message
field.
- Parameters:
csv
List of members who have opted to have their info in public. If the query
parameter csv
is true-ish, returns results as csv rather than json format.
[
{ country, membership, first_name, last_name },
…
]
- Parameters:
csv
Membership statistics by country. If the query parameter csv
is true-ish,
returns results as csv rather than json format.
{
Finland: { Adult: 13, …, total: 26 },
…,
'': { Adult: 131, …, total: 262 }
}
The configuration used by this instance.
{
id: 'w75',
name: 'Worldcon 75',
paid_paper_pubs: true,
membershipTypes: {
Adult: {
badge: true,
hugo_nominator: true,
member: true,
wsfs_member: true
},
...
}
}
- Parameters:
email
,name
,path
,reset
If email
matches (case-insensitively) a known address, send a login link to
that address. If no key exists or reset
is true-ish, generate a new key. If
no match is found for email
and name
is set, create a new non-member account
and login key, and send a login link to email
. If path
is set, it will be
included in the login link as the value of the next
query parameter.
{
status: 'success',
email: '[email protected]'
}
- Parameters:
email
,key
Fails with HTTP status 400
for missing input values, 401
for incorrect
email
/key
combinations, and 403
for expired key
(which triggers a key
reset and sends an email with an updated login link). Creates a new session
object for valid credentials.
Set-Cookie: w75=sessionId
{
status: 'success',
email
}
- Requires authentication
- Parameters:
all
,reset
,email
(admin_admin
only)
Removes the user information from the current session. If email
is set in the
parameters, the session user needs admin_admin
authority; otherwise it's read
from session data. If all
is set, all of the user's sessions are terminated.
If reset
is set, the user's key is also reset, and will need to be
re-requested.
{
status: 'success',
email,
opt: undefined | 'all' | 'reset',
sessions: undefined | #
}
- Requires authentication
- Parameters:
email
(member_admin
only)
If email
is not set, its value is read from session data. Returns the
memberships matching the given email address, and the roles (e.g.
"member_admin"
) assigned to this email address.
{
email,
people: [ { id, membership, legal_name, … }, … ],
roles: [ … ]
}
- Requires authentication
- Parameters:
email
(member_admin
only)
If email
is not set, its value is read from session data. Returns the
log entries with author
set to the given email address.
{
email,
log: [ … ]
}
- Requires authentication and
member_admin
ormember_list
authority - Parameters:
since
,name
, and all person fields
List member data. If no query parameters are present, the response array
contains all members and is padded with null
values such that
response[id].id == id
, and fields with null
or false
values are left out
of the response.
since
will return entries with a last_modified
value (ISO 8601 date) greater
than specified. name
is shorthand for searching among all three name fields.
All text fields are compared using the postgres case-insensitive ILIKE
, which
uses _
for single-character wildcards and %
for multiple characters.
[
{ id, last_modified, member_number, legal_name, email, … },
…
]
- Requires authentication and
member_admin
authority - Parameters:
membership
,legal_name
,email
,public_first_name
,public_last_name
,city
,state
,country
,paper_pubs
Add new person. If membership
is not 'NonMember'
, a new member_number
will
be generated.
{
status: 'success',
id,
member_number
}
- Requires authentication
Find the person matching id
. If its email address does not match the session
data, member_admin
or member_list
authority is required.
{
id, last_modified, member_number, membership, legal_name, email,
public_first_name, public_last_name, city, state, country,
paper_pubs: { name, address, country },
preferred_name, daypass, daypass_days
}
- Requires authentication
Find the log entries for the person matching id
. If its email address does not
match the session data, member_admin
or member_list
authority is required.
[
{ timestamp: …, author: …, subject: …, action: …, … },
…
]
- Requires authentication
- Parameters:
membership
(member_admin
only),email
(member_admin
only),legal_name
,public_first_name
,public_last_name
,city
,state
,country
,paper_pubs
Update the data for the person matching id
. If its email address does not
match the session data, member_admin
authority is required.
If set, the paper_pubs
value is required to be a JSON object with non-empty
values for the fields name
, address
, and country
. If the user does not
member_admin
authority, it also needs to have been previously set to a
non-null value.
{
status: 'success',
updated: [ 'legal_name', … ]
}
- Requires authentication and
member_admin
authority - Parameters:
membership
,member_number
(admin_admin
only),paper_pubs
Increase membership level, generating a member_number
if not set in parameters
or previously set. Also handles paper_pubs
purchases, connected or separately
from membership changes.
{
status: 'success',
member_number,
updated: [ 'membership', 'member_number', 'paper_pubs' ]
}
- Parameters:
email
,member_number
,name
Finds a person's id
, membership
and name
based on a slightly fuzzy lookup
given some subset of the parameters email
, member_number
, and name
. If the
lookup matches more than one hit, status
will be multiple
. If no matches are
found, status
will be not found
. Child and Kid-in-tow members are not
included in the results.
{
status: 'success',
id,
membership,
name
}
- Requires authentication and
member_admin
authority
WebSocket connection endpoint. The server won't listen to any messages sent to it, but will broadcast updates to People as they happen. Each message will contain as its data a JSON string representation of a single updated person.
The API uses the app-specific codes 4001
and 4004
on WebSocket 'close'
events to signal 'Unauthorized'
and 'Not Found'
(respectively) to the client.
'{"id":#,"member_number":…,"legal_name":…,…}'
- Parameters:
account
,amount
,email
,source
,new_members: [ { membership, email, legal_name, public_first_name, public_last_name, city, state, country, paper_pubs }, ... ]
,upgrades: [ { id, membership, paper_pubs }, ... ]
Using the source
(or token) object received from Stripe, make a charge of
amount
on the card (once verified against the server-side calculated sum from
the items) and add the new_members
to the database as well as applying the
specified upgrades
. For new members, generate a login key and include it in
the welcome email sent to each address. Sends an info message to each new or
upgraded member.
{
status: 'success',
charge_id
}
Current purchase data for non-membership purchases. Top-level keys correspond to
pre-defined payment categories and their types
. shape
values define the
shapes of the expected data
object, with matching JS type
. Shape values with
required: true
need to have a non-empty value in the matching request.
{
new_member: {
label: 'New membership',
allow_create_account: true,
shape: [
{
key: membership,
type: string,
label: 'Membership type'
},
...
],
types: [
{
key: 'Adult',
label: 'Adult',
amount: 19500
},
...
]
},
sponsor: {
label: 'Sponsorship',
listed: true,
description: 'Why not sponsor ...',
shape: [
{
key: 'sponsor',
type: 'string',
label: 'Sponsor name',
required: true
},
...
],
types: [
{
key: 'bench',
label: 'Sponsored bench plaque',
amount: 6000,
description: '<p>Fannish Tradition ....</p>'
},
...
]
},
...
}
Current public Stripe keys. Includes at least the default
key. If a non-default
key is used, its name should be passed to POST
purchase calls as the value of
account
.
{
default: 'pk_test_...',
...
}
Purchases made using this account's email
address, or one set as a query
parameter (requires member_admin
access).
[
{
id: 123,
timestamp: '2017-03-24 06:49:57.229836+00',
amount: 200000,
currency: 'eur',
stripe_charge_id: '...',
category: 'Sponsorship',
type: 'bench',
payment_email: '...',
person_id: 456,
person_name: '...',
data: { sponsor: '...' },
comments: '...',
invoice: '456'
},
...
]
Parameters:
account
: Optional, used to set indicate an alternative Stripe account nameemail
: They payer's email addresssource: { id, ... }
: Received from Stripe, used to make the chargeitems
: Array of payment objects, each consisting of:amount
,currency
: The charge amount, in integer cents ofcurrency
person_id
,person_name
: The beneficiary of the payment (optional)category
,type
,data
: Required to match entries returned byGET purchase/data
comments
,invoice
: Optional strings
Using the source
received from Stripe, make a charge on the card or account
and adds entries to the Payments
table for each item. Sends an info email to
each item's beneficiary.
{
email: '...',
source: { id: '...' },
items: [
{
amount: 200000,
currency: 'eur',
category: 'Sponsorship',
type: 'bench',
data: { sponsor: '...' },
person_id: 123,
person_name: '...',
comments: '...',
invoice: '456'
}
]
}
{
status: 'succeeded' || 'pending' || 'failed',
charge_id: '...'
}
Send the user an invitation via email to join the organisation's Slack. Requires
the env vars SLACK_ORG
and SLACK_TOKEN
to be set, with the token having both
the client
and admin
permission scopes granted. Attempting to re-send an
invitation will return an error.
{
success: true,
email
}