{% extends "base.html" %} {% block title %}API Key: {{ api_key.name }} — {{ club.name }}{% endblock %} {% block content %}
{{ new_raw_key }}
| Prefix | {{ api_key.prefix }}… |
|---|---|
| Status | {% if api_key.is_active %}Active{% else %}Revoked{% endif %} |
| Created | {{ api_key.created_at|date:"N j, Y g:i a" }} |
| Last used | {{ api_key.last_used_at|date:"N j, Y g:i a"|default:"Never" }} |
Track activity for this key in club history — search for {{ api_key.prefix }}.
| Add club members | {% if api_key.can_add_club_members %}Enabled{% else %}Disabled{% endif %} |
|---|---|
| Read club member list | {% if api_key.can_read_club_member_list %}Enabled{% else %}Disabled{% endif %} |
| Update club members | {% if api_key.can_update_club_members %}Enabled{% else %}Disabled{% endif %} |
| BAP points and lots Add points to members, and read the lots from this club's auctions | {% if api_key.can_add_bap_points %}Enabled{% else %}Disabled{% endif %} |
| Renew memberships | {% if api_key.can_renew_memberships %}Enabled{% else %}Disabled{% endif %} |
X-API-Key header (or Authorization: Api-Key <key>).Content-Type: application/json and send a JSON body.
POST https://{{ site_domain }}/api/v1/clubs/{{ club.slug }}/members/{"name":"Mike","email":"mike@example.com"}
GET https://{{ site_domain }}/api/v1/clubs/{{ club.slug }}/members/?name=mike —
or use the same text filter as the admin member list: ?filter=expired, ?filter=mike, etc.
(tokens: discord, current, expired, expiring, never paid, or any name/email text)
PATCH https://{{ site_domain }}/api/v1/clubs/{{ club.slug }}/members/{{ example_member_id|default:"123" }}/{"email":"mike@example.com"}
POST https://{{ site_domain }}/api/v1/clubs/{{ club.slug }}/members/{{ example_member_id|default:"123" }}/bap-awards/{"points":5,"notes":"Bred angelfish","email":"mike@example.com"}
GET https://{{ site_domain }}/api/v1/clubs/{{ club.slug }}/bap-lots/winner_name and winner_email blank.
?days=90, or with explicit dates: ?start=2026-01-01&end=2026-03-31.
Dates are inclusive on both ends (end=2026-03-31 covers all of March 31st) and are read in
the site's local time; full ISO 8601 timestamps work in place of a date, and start/end
take precedence over days. The response echoes the exact range it used, in UTC.
lot_id, which is
permanent and never reused, so a lot you've already handled is easy to skip. bap_award also tells you
whether this site has already recorded points for the lot.
curl "https://{{ site_domain }}/api/v1/clubs/{{ club.slug }}/bap-lots/?days={{ bap_lot_default_days }}" \
-H "X-API-Key: {{ api_key.prefix }}.YOUR_SECRET"
start/end echo back the range that was used:{
"start": "{{ example_bap_range_start }}",
"end": "{{ example_bap_range_end }}",
"count": 1,
"results": [
{
"lot_id": 84213,
"lot_number_display": "12",
"lot_name": "6 Corydoras panda fry",
"quantity": 6,
"seller_name": "Mike Smith",
"seller_email": "mike@example.com",
"winner_name": "Dana Lee",
"winner_email": "dana@example.com",
"timestamp": "{{ example_bap_lot_timestamp }}",
"sold": true,
"category": "Catfish",
"program": "BAP",
"i_bred_this_fish": true,
"donation": false,
"custom_checkbox": false,
"custom_checkbox_name": "",
"bap_eligible": true,
"bap_ineligible_reason": "",
"bap_ineligible_reason_display": "",
"bap_auto_reason": "",
"bap_points_awarded": 5,
"manually_approved": false,
"bap_award": {
"id": 991,
"date": "{{ example_bap_award_date|date:"Y-m-d" }}",
"points": 5,
"hap_points": 0,
"cap_points": 0,
"notes": "",
"auto_awarded": true
}
}
]
}
"sold": false, blank winner fields, "bap_award": null, and (for a club that only gives points for sold lots) "bap_ineligible_reason": "not_sold".POST https://{{ site_domain }}/api/v1/clubs/{{ club.slug }}/members/renew/email (required) and added to the club if
they're new, then their membership is renewed the same way the Renew button on the
member list does: {% if club.membership_system == "january_first" %}the expiration moves to the next
January 1st{% else %}the expiration moves a year forward, from the current expiration if it hasn't
passed yet{% endif %}, the club history and treasurer's report record the renewal, and the member
gets the renewal confirmation email{% if not club.send_membership_renewal_confirmation %} (currently
turned off in this club's email settings){% endif %}. Any other field this key may write can ride
along and is applied before the renewal; blank values are ignored instead of clearing what's on file.
curl -X POST https://{{ site_domain }}/api/v1/clubs/{{ club.slug }}/members/renew/ \
-H "X-API-Key: {{ api_key.prefix }}.YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{"email":"mike@example.com","first_name":"Mike","last_name":"Smith","phone_number":"555-0143"}'
200 for an existing member, 201 when one was created:{
"created": false,
"id": {{ example_member_id|default:"123" }},
"name": "Mike Smith",
"email": "mike@example.com",
"membership_number": 1234567890,
"membership_last_paid": "{{ example_last_paid|date:"Y-m-d" }}",
"membership_expiration_date": "{{ example_new_expiration|date:"Y-m-d" }}",
"wallet_link": "https://{{ site_domain }}/clubs/{{ club.slug }}/member/<uuid>/",
...
}
Map incoming field names to club member fields. Unmapped fields are passed through unchanged if they match an allowed field name.
Members store a single name field. If first_name and/or last_name are sent (or mapped) instead, they will be combined into name.
Field mapping applies to club member create and update payloads. BAP point requests always use the fixed points, date, and notes fields directly.
| External field (incoming) | Internal field | |
|---|---|---|
{{ mapping.external_field }} |
{{ mapping.internal_field }} |
No mappings yet.
{% endif %} {% if api_key.is_active %}{{ field }}{% if not forloop.last %}, {% endif %}{% endfor %}