Members > Invite and activate members
Invite member
POST /organizations/{org_id}/users/invite
This endpoint sends an invitation email to a new user, prompting them to join your Tallyfy organization.
Replace {org_id}
with your Organization ID.
Authorization: Bearer {your_access_token}
Accept: application/json
X-Tallyfy-Client: APIClient
Content-Type: application/json
The request body requires a JSON object containing the details of the user to invite.
Refer to the #definitions/inviteInput
schema in Swagger. Key fields:
email
(string, required): The email address of the person to invite.first_name
(string, optional): First name of the invitee.last_name
(string, optional): Last name of the invitee.role
(string, optional): The role to assign upon joining (e.g.,standard
,light
,admin
). Defaults may apply if omitted.timezone
(string, optional): Timezone for the new user (e.g.,America/New_York
).
Example Body:
{ "email": "new.user@example.com", "first_name": "Charlie", "last_name": "Brown", "role": "standard"}
const accessToken = 'YOUR_PERSONAL_ACCESS_TOKEN';const orgId = 'YOUR_ORGANIZATION_ID';const apiUrl = `https://go.tallyfy.com/api/organizations/${orgId}/users/invite`;
const inviteData = { email: "charlie.brown@example.com", first_name: "Charlie", last_name: "Brown", role: "standard" // Valid roles: "standard", "light", "admin"};
const headers = new Headers();headers.append('Authorization', `Bearer ${accessToken}`);headers.append('Accept', 'application/json');headers.append('X-Tallyfy-Client', 'APIClient');headers.append('Content-Type', 'application/json');
fetch(apiUrl, { method: 'POST', headers: headers, body: JSON.stringify(inviteData)}).then(response => { return response.json().then(data => { // Attempt to parse JSON regardless of status if (!response.ok) { console.error("Failed to invite member:", data); // Check for specific errors like 422 (user already exists) let errorMessage = `HTTP error! status: ${response.status}`; if (data && data.message) { errorMessage += `, message: ${data.message}`; } else if (data) { errorMessage += `, details: ${JSON.stringify(data)}`; } throw new Error(errorMessage); } return data; // Pass successful data along });}).then(data => { console.log('Successfully invited member:'); console.log(JSON.stringify(data, null, 2));}).catch(error => { console.error('Error inviting member:', error.message);});
import requestsimport jsonimport os
access_token = os.environ.get('TALLYFY_ACCESS_TOKEN', 'YOUR_PERSONAL_ACCESS_TOKEN')org_id = os.environ.get('TALLYFY_ORG_ID', 'YOUR_ORGANIZATION_ID')api_url = f'https://go.tallyfy.com/api/organizations/{org_id}/users/invite'
headers = { 'Authorization': f'Bearer {access_token}', 'Accept': 'application/json', 'X-Tallyfy-Client': 'APIClient', 'Content-Type': 'application/json'}
invite_payload = { 'email': 'lucy.vanpelt@example.com', 'first_name': 'Lucy', 'last_name': 'Van Pelt', 'role': 'light' # Valid Tallyfy roles: standard, light, admin}
response = Nonetry: response = requests.post(api_url, headers=headers, json=invite_payload) response.raise_for_status() # Raises HTTPError for bad responses (4xx or 5xx)
invite_response = response.json() print('Successfully invited member:') print(json.dumps(invite_response, indent=4))
except requests.exceptions.HTTPError as http_err: error_details = "" try: if response is not None: error_details = response.json() # Try to get JSON error details except json.JSONDecodeError: if response is not None: error_details = response.text # Fallback to text
print(f"HTTP error occurred inviting member: {http_err}") print(f"Response Body: {error_details}")
except requests.exceptions.RequestException as req_err: print(f"Request failed inviting member: {req_err}")except json.JSONDecodeError: print("Failed to decode successful JSON response after invite") if response is not None: print(f"Response Text: {response.text}")except Exception as err: print(f"An unexpected error occurred: {err}")
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.io.IOException;// Requires a JSON library like Jackson or Gson// import com.fasterxml.jackson.databind.ObjectMapper;// import java.util.Map;// import java.util.HashMap;
public class InviteMember { public static void main(String[] args) { String accessToken = System.getenv().getOrDefault("TALLYFY_ACCESS_TOKEN", "YOUR_PERSONAL_ACCESS_TOKEN"); String orgId = System.getenv().getOrDefault("TALLYFY_ORG_ID", "YOUR_ORGANIZATION_ID"); String apiUrl = "https://go.tallyfy.com/api/organizations/" + orgId + "/users/invite";
// --- Payload Construction --- // Using Jackson/Gson is recommended: /* ObjectMapper mapper = new ObjectMapper(); Map<String, String> inviteData = new HashMap<>(); inviteData.put("email", "linus.vanpelt@example.com"); inviteData.put("first_name", "Linus"); inviteData.put("role", "standard"); // Use "light" or "admin" if needed String jsonPayload; try { jsonPayload = mapper.writeValueAsString(inviteData); } catch (Exception e) { System.err.println("Failed to serialize JSON: " + e.getMessage()); return; } */ // Simple manual JSON string for example: String jsonPayload = "{\"email\": \"linus@example.com\", \"first_name\": \"Linus\", \"role\": \"standard\"}"; // --- End Payload ---
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(apiUrl)) .header("Authorization", "Bearer " + accessToken) .header("Accept", "application/json") .header("X-Tallyfy-Client", "APIClient") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) .build();
try { HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200 || response.statusCode() == 201) { // API might return 201 Created System.out.println("Successfully invited member:"); System.out.println(response.body()); // TODO: Consider parsing the JSON response } else { // Common error: 422 if user already exists System.err.println("Failed to invite member. Status: " + response.statusCode()); System.err.println("Response Body: " + response.body()); } } catch (IOException | InterruptedException e) { System.err.println("Request failed: " + e.getMessage()); Thread.currentThread().interrupt(); } catch (Exception e) { System.err.println("An unexpected error occurred: " + e.getMessage()); e.printStackTrace(); } }}
package main
import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" "os" "time")
func main() { accessToken := os.Getenv("TALLYFY_ACCESS_TOKEN") if accessToken == "" { accessToken = "YOUR_PERSONAL_ACCESS_TOKEN" } orgId := os.Getenv("TALLYFY_ORG_ID") if orgId == "" { orgId = "YOUR_ORGANIZATION_ID" } apiUrl := fmt.Sprintf("https://go.tallyfy.com/api/organizations/%s/users/invite", orgId)
inviteData := map[string]interface{}{ "email": "snoopy@example.com", "first_name": "Snoopy", "role": "light", // Valid Tallyfy roles: standard, light, admin }
jsonData, err := json.Marshal(inviteData) if err != nil { fmt.Printf("Error marshalling JSON: %v\n", err) return }
client := &http.Client{Timeout: 15 * time.Second} req, err := http.NewRequest(http.MethodPost, apiUrl, bytes.NewBuffer(jsonData)) if err != nil { fmt.Printf("Error creating invite request: %v\n", err) return }
req.Header.Set("Authorization", "Bearer "+accessToken) req.Header.Set("Accept", "application/json") req.Header.Set("X-Tallyfy-Client", "APIClient") req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req) if err != nil { fmt.Printf("Error executing invite request: %v\n", err) return } defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Printf("Error reading invite response body: %v\n", err) return }
// API might return 201 Created on success if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { // Common error: 422 if user already exists fmt.Printf("Failed to invite member. Status: %d\nBody: %s\n", resp.StatusCode, string(body)) return }
fmt.Println("Successfully invited member:") // Pretty print JSON response var prettyJSON bytes.Buffer if err := json.Indent(&prettyJSON, body, "", " "); err == nil { fmt.Println(prettyJSON.String()) } else { fmt.Println(string(body)) } // TODO: Unmarshal JSON if needed}
#include <iostream>#include <string>#include <cpprest/http_client.h>#include <cpprest/json.h>
using namespace web;using namespace web::http;using namespace web::http::client;using namespace web::json;
pplx::task<void> InviteTallyfyMember(const value& invitePayload){ utility::string_t accessToken = U("YOUR_PERSONAL_ACCESS_TOKEN"); utility::string_t orgId = U("YOUR_ORGANIZATION_ID"); utility::string_t apiUrl = U("https://go.tallyfy.com/api/organizations/") + orgId + U("/users/invite");
http_client client(apiUrl); http_request request(methods::POST);
request.headers().add(U("Authorization"), U("Bearer ") + accessToken); request.headers().add(U("Accept"), U("application/json")); request.headers().add(U("X-Tallyfy-Client"), U("APIClient")); request.headers().set_content_type(U("application/json")); request.set_body(invitePayload);
return client.request(request).then([](http_response response) { return response.extract_json().then([response](pplx::task<value> task) { try { value const & body = task.get(); // API might return 201 Created if (response.status_code() == status_codes::OK || response.status_code() == status_codes::Created) { std::wcout << L"Successfully invited member:\n" << body.serialize() << std::endl; // Access data: body[U("data")][U("id")].as_integer(); } else { // Common error: 422 Unprocessable Entity if user exists std::wcerr << L"Failed to invite member. Status: " << response.status_code() << L"\nResponse: " << body.serialize() << std::endl; } } catch (const http_exception& e) { std::wcerr << L"HTTP exception during invite member: " << e.what() << std::endl; } catch (const std::exception& e) { std::wcerr << L"Exception during invite member response handling: " << e.what() << std::endl; } }); });}
int main() { try { value payload = value::object(); payload[U("email")] = value::string(U("peppermint.patty@example.com")); payload[U("first_name")] = value::string(U("Peppermint")); payload[U("last_name")] = value::string(U("Patty")); payload[U("role")] = value::string(U("standard"));
InviteTallyfyMember(payload).wait(); } catch (const std::exception &e) { std::cerr << "Error in main: " << e.what() << std::endl; } return 0;}// Requires C++ REST SDK (Casablanca)
using System;using System.Net.Http;using System.Net.Http.Headers;using System.Text;using System.Text.Json;using System.Threading.Tasks;
public class TallyfyMemberInviter{ private static readonly HttpClient client = new HttpClient();
public class InvitePayload { public string Email { get; set; } // Required public string FirstName { get; set; } public string LastName { get; set; } public string Role { get; set; } // e.g., "standard", "light", "admin" public string Timezone { get; set; } // Add other optional fields as needed }
public static async Task InviteMemberAsync(InvitePayload payload) { var accessToken = Environment.GetEnvironmentVariable("TALLYFY_ACCESS_TOKEN") ?? "YOUR_PERSONAL_ACCESS_TOKEN"; var orgId = Environment.GetEnvironmentVariable("TALLYFY_ORG_ID") ?? "YOUR_ORGANIZATION_ID"; var apiUrl = $"https://go.tallyfy.com/api/organizations/{orgId}/users/invite";
if (string.IsNullOrWhiteSpace(payload?.Email)) { Console.WriteLine("Error: Email is required to invite a member."); return; }
try { using var request = new HttpRequestMessage(HttpMethod.Post, apiUrl); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Headers.Add("X-Tallyfy-Client", "APIClient");
// Serialize the payload, ignoring nulls var options = new JsonSerializerOptions { DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull }; string jsonPayload = JsonSerializer.Serialize(payload, options); request.Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.SendAsync(request); string responseBody = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode) // Check for 200 OK or 201 Created { Console.WriteLine("Successfully invited member:"); try { using var doc = JsonDocument.Parse(responseBody); Console.WriteLine(JsonSerializer.Serialize(doc.RootElement, new JsonSerializerOptions { WriteIndented = true })); } catch (JsonException) { Console.WriteLine(responseBody); } } else { // Common error: 422 Unprocessable Entity if user already exists Console.WriteLine($"Failed to invite member. Status: {response.StatusCode}"); Console.WriteLine($"Response: {responseBody}"); } } catch (HttpRequestException e) { Console.WriteLine($"Request Exception: {e.Message}"); } catch (JsonException jsonEx) { Console.WriteLine($"JSON Serialization Error: {jsonEx.Message}"); } catch (Exception ex) { Console.WriteLine($"An unexpected error occurred: {ex.Message}"); } }
// Example Usage: // static async Task Main(string[] args) // { // var newInvite = new InvitePayload { // Email = "marcie@example.com", // FirstName = "Marcie", // Role = "light" // }; // await InviteMemberAsync(newInvite); // }}
A successful request returns a 200 OK
or 201 Created
status code. The response body typically contains the details of the invited user, often showing a pending
or invited
status until they accept.
{ "data": { "id": 1005, // User ID assigned even before acceptance "email": "charlie.brown@example.com", "username": null, // Username set upon acceptance "first_name": "Charlie", "last_name": "Brown", "full_name": "Charlie Brown", "profile_pic": null, "active": false, // Not active until accepted "is_suspended": false, "created_at": "2024-05-21T10:00:00Z", "last_updated": "2024-05-21T10:00:00Z", "last_login_at": null, "activated_at": null, // Null until accepted "status": "invited", // Or similar status "user_role": "Standard" // ... other properties ... }}
If the email address already belongs to an existing member of the organization, you will likely receive a 422 Unprocessable Entity
error.
Administrators can invite new members by sending email invitations which recipients must activate to gain account access while managing invites and member statuses through the organization settings.
The POST endpoint creates guest users in an organization by accepting JSON data with required email and optional fields like name and company details while returning the newly created guest’s information upon success.
Code Samples > Managing members (Users)
The API enables organizations to manage their registered users through functionalities like inviting listing updating and removing members along with their roles and profiles.
A POST endpoint that creates organizational groups by accepting JSON data containing group name description members and guests while providing code samples in multiple programming languages and returning the newly created group details.
About Tallyfy
- 2025 Tallyfy, Inc.
- Privacy Policy
- Terms of Use
- Report Issue
- Trademarks