Mobile

API

These endpoints are public. Send Accept: application/json. Signed-in calls also send Authorization: Bearer {token}.

https://raqets.com/api/v1

Account

POST /auth/register No token

Creates a player or organiser and returns a token. A welcome email is sent. The response status is 201.

Send

name, email, password, password_confirmation
role is optional: player or organiser. Left off, the account is a player.
password is at least 8 characters.

Returns

{ "user": { "id", "name", "email", "role" }, "token": "...", "token_type": "Bearer" }
POST /auth/login No token

Checks the email and password. A wrong password returns 422 with "Invalid credentials."

Send

email, password

Returns

{ "user", "token", "token_type": "Bearer" }
GET /auth/user Token required

Returns the account that owns the token. Switching to a child does not change this. The password is not included.

Returns

{ "id", "name", "email", "role", "guardian_id" }
POST /auth/logout Token required

Deletes the token used for this call.

Returns

{ "message": "Logged out." }

Family

The token always belongs to the account that signed in. A linked child has no email, so the child never logs in. Call switch to choose which profile this token acts as. Profile, photos, tournament signups, players, and friends then use that profile. Another device signed in as the same account can stay on a different child. Saving a score still checks the account’s role.

GET /profiles Token required

The account and each linked child. active_id is the profile later calls will use. Until you switch, that is the account.

Returns

{ "active_id", "profiles": [{ "id", "name", "photo_url", "kind": "account or child" }] }
POST /profiles/switch Token required

Chooses the account or one of its linked children. Any other id returns 403. Switching back uses the account id.

Send

{ "user_id": 48 }

Returns

{ "active_id", "profile": { "id", "name", "photo_url", "kind" } }

Profile

One call returns the active profile, every profile field, photo and cover addresses, interests, tournament signups, and accepted friends. Photo and cover addresses are full URLs. Email can be changed only while the account itself is active.

GET /profile Token required

The active profile. This is the account until you switch, then the chosen child.

Returns

{ "user", "profile", "tournaments", "friends" }
PUT /profile Token required

Updates the profile. Send only the fields that changed. interests is a list of up to 20 labels, each up to 40 characters. Repeated labels are kept once.

Send

first_name, middle_name, last_name, email
gender, cell and home and work phones
date_of_birth, show_full_birthday, timezone, display_language
address lines, city, postal_code, country, state_province, region, district
membership_number, is_coach, is_official
south_african_citizen, identification_number, ethnic_group
tournament_player, coach, nationality, handedness
summary, nicknames, occupation, sporting_idols, website
birthplace, children_count, dietary_considerations
playing_time_preferences, interests

Returns

The same shape as GET /profile.

Photos

Send the file as multipart form data. Allowed types are jpg, png, and webp.

POST /profile/photo Token required

Sets the profile photo. The field name is photo. Maximum size is 2 MB.

Send

photo

Returns

The profile, with profile.photo_url filled in.
DELETE /profile/photo Token required

Removes the profile photo.

Returns

The profile, with profile.photo_url set to null.
POST /profile/cover Token required

Sets the cover photo. The field name is cover. Maximum size is 4 MB.

Send

cover

Returns

The profile, with profile.cover_url filled in.
DELETE /profile/cover Token required

Removes the cover photo.

Returns

The profile, with profile.cover_url set to null.

Tournaments

Search lists every tournament that is not a draft. Drafts are hidden. Signing up and withdrawing use the active profile, so switch to a child first when the entry should be in the child’s name. A free draw is entered straight away. A draw with an entry fee returns a payment instead, and the player is entered only after PayFast confirms it. Post payfast.fields as a form to payfast.url. Card details go to PayFast, not to Raqets. When confirm_locally is true, PayFast is not set up and the app can confirm the fee on this server.

GET /tournaments/search Token required

All published tournaments, newest start date first. Leave a filter off to ignore it. q matches the tournament name or the club name, city, or province. province must be one of the provinces in the response. club is a club id from clubs. from and to are dates, YYYY-MM-DD. from keeps tournaments that have not ended before that day. to keeps tournaments that start on or before that day. status is entries_open, in_progress, or completed. page starts at 1. per_page defaults to 15 and cannot be more than 50.

Send

q, province, club, from, to, status
page, per_page

Returns

{ "tournaments": [{ "id", "name", "status", "status_label", "starts_on", "ends_on", "entry_fee_cents", "entry_fee", "club": { "id", "name", "city", "province" }, "draws": [{ "id", "name", "format", "format_label", "gender", "age", "locked", "limit", "entered_count", "open" }] }],
"provinces": [],
"clubs": [{ "id", "name" }],
"meta": { "current_page", "last_page", "per_page", "total" } }
GET /tournaments/{id} Token required

One tournament and each draw, for the active profile. entered is true when that profile is already in the draw. blocked is why that profile cannot enter, or null when they can. open is false when the draw is locked, full, or the tournament is not taking entries. A draft returns 404.

Returns

{ "tournament": { the search tournament, plus "description", and each draw also has "entered", "registration_id", "blocked" } }
POST /tournaments/{id}/draws/{draw} Token required

Signs the active profile up for that draw. A free entry returns 201 and the registration. An entry fee returns 200 with entered false and a payment; nobody is in the draw until that payment is finished. A locked draw, a closed tournament, a full draw, a second entry, or a profile that does not match the draw returns 422 with message.

Returns

{ "entered": true, "message", "registration" }
or
{ "entered": false, "message", "payment": { "id", "status", "amount", "amount_cents", "currency": "ZAR", "confirm_locally", "payfast": { "url", "fields" } } }
POST /tournaments/{id}/payments/{payment} Token required

Finishes a pending entry when confirm_locally is true. Otherwise this returns 403. The payment must belong to this tournament and the active profile.

Returns

{ "entered", "message", "registration" }
DELETE /tournaments/registrations/{id} Token required

Withdraws the active profile from that draw. Another profile’s entry returns 403. A locked draw returns 422 and the entry stays.

Returns

{ "message": "Registration withdrawn." }
GET /tournaments Token required

Tournaments the active profile is already signed up for. The same list is included on GET /profile. This is not the full catalogue. Use search for that.

Returns

{ "tournaments": [{ "registration_id", "seed", "draw": { "id", "name" }, "tournament": { "id", "name", "starts_on", "ends_on", "status", "club" } }] }

Scores

There is no live socket. Poll GET /scores/tournaments/{id} every few seconds and replace the screen when as_of changes. Any signed-in player can read. Only an organiser, official, or super admin can save a score.

Each draw has layout. bracket is a knockout or Monrad draw: read brackets, and inside each one read rounds from left to right. The labels are Quarter-finals, Semi-finals, and Final. A Monrad draw adds a bracket for each place, such as 5th–8th. tables is a round robin: read tables. Each table is one box. rows are the players in sheet order. cells line up with those same players, and the player’s own cell is null. points and position are the Pts and Pos columns. Knockout play-offs after the boxes are in playoffs, again as rounds.

GET /scores Token required

Every tournament that is not a draft, whether or not a score sheet exists. A draw with locked false is not ready for scores yet.

Returns

{ "tournaments": [{ "id", "name", "status", "starts_on", "ends_on", "club", "draws": [{ "id", "name", "format", "format_label", "locked" }] }] }
GET /scores/tournaments/{id} Token required

The live board. as_of is the latest match change. A draw with layout bracket fills brackets and leaves tables empty. A draw with layout tables fills tables and playoffs.

Returns

{ "tournament", "as_of", "draws": [{ "id", "name", "format", "layout", "scoring", "locked", "brackets", "tables", "playoffs" }] }
PUT /scores/matches/{id} Token required

Saves a result and returns that draw so the screen can replace it. home is player_one’s games, away is player_two’s games. A 7-6 set needs tiebreak, the loser’s tie-break points. Walkover, default, and retirement name the player. The score sheet must already be generated.

Send

outcome: score, walkover, default, retirement, or no_result
sets: [{ "home": 6, "away": 4 }, { "home": 7, "away": 6, "tiebreak": 5 }]
winner_id for a walkover
retired_id for a retirement
defaulted_id for a default
court and scheduled_at are optional

Returns

{ "draw": { the same draw object as on the board } }

Players

GET /players?q= Token required

Finds other players by name. q needs at least 2 letters. A shorter search returns an empty list. Email addresses are not included. At most 10 players are returned.

Returns

{ "players": [{ "id", "name", "photo_url" }] }

Friends

Friend requests belong to the active profile. One player sends a request. The other accepts it. Either player can remove the friendship.

GET /friends Token required

Accepted friends, plus requests waiting on you and requests you have sent.

Returns

{ "friends": [], "incoming": [], "outgoing": [] }
POST /friends Token required

Sends a friend request. A new request returns 201. You cannot add yourself. If that player already asked you, the response is 422 and tells you to accept their request.

Send

{ "user_id": 12 }

Returns

{ "friendship": { "id", "status": "pending", "user": { "id", "name", "photo_url" } } }
POST /friends/{id}/accept Token required

Accepts a request sent to you. Only the player who received it can accept.

Returns

{ "friendship": { "id", "status": "accepted", "user" } }
DELETE /friends/{id} Token required

Cancels a request you sent, declines one you received, or removes an accepted friend.

Returns

{ "message": "Friend removed." }