Start here
Invite someone to a project
POST
/v1/studio/projects/{project}/inviteson https://api.auray.ai/v1Invite somebody by email, or make an invitation link to pass on yourself.
Invite somebody by email, or make an invitation link to pass on yourself. An email invitation is mailed to the address in the invited account's language; inviting an address again replaces its waiting invitation. A link's answer carries its url once — the token is kept nowhere but there and in the email, and the database holds only its SHA-256. Takes a key holding studio:write — Account offers it unticked — or the desktop's own session key. Spends nothing.
#Authentication
Authorization: Bearer auray_sk_… — a key with the scope the route names.
#Request
#Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
project | string | yes |
#Body
application/json, required.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | string | yes | — | One of "email", "link". |
email | string | no | — | For kind: email. 0 to 254 characters. |
role | string | yes | — | One of "admin", "collaborator", "viewer". |
days | integer | no | 7 | How long it opens the project. One of 1, 7, 30. |
uses_max | integer | no | — | A link's most admissions; left out, until it expires. 1 to 50. |
#Example request
curl -X POST https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/invites \
-H "Authorization: Bearer $AURAY_API_KEY" \
-H "content-type: application/json" \
-d '{
"kind": "email",
"email": "mara@example.com",
"role": "collaborator",
"days": 7
}'const res = await fetch("https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/invites", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AURAY_API_KEY}`,
"content-type": "application/json",
},
body: JSON.stringify({
"kind": "email",
"email": "mara@example.com",
"role": "collaborator",
"days": 7
}),
});
console.log(await res.json());import os, requests
r = requests.post(
"https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/invites",
headers={"Authorization": f"Bearer {os.environ['AURAY_API_KEY']}"},
json={
"kind": "email",
"email": "mara@example.com",
"role": "collaborator",
"days": 7
},
)
r.raise_for_status()
print(r.json())package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
)
func main() {
body := []byte(`{
"kind": "email",
"email": "mara@example.com",
"role": "collaborator",
"days": 7
}`)
req, err := http.NewRequest("POST", "https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/invites", bytes.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("AURAY_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.Status, string(out))
}<?php
$ch = curl_init("https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/invites");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("AURAY_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"kind" => "email",
"email" => "mara@example.com",
"role" => "collaborator",
"days" => 7,
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), " ", $response, PHP_EOL;require "net/http"
require "json"
uri = URI("https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/invites")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch("AURAY_API_KEY")}"
req["Content-Type"] = "application/json"
req.body = {
"kind" => "email",
"email" => "mara@example.com",
"role" => "collaborator",
"days" => 7
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.code, res.bodyimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String body = """
{
"kind": "email",
"email": "mara@example.com",
"role": "collaborator",
"days": 7
}""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/invites"))
.header("Authorization", "Bearer " + System.getenv("AURAY_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("AURAY_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Post, "https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/invites");
var body = """
{
"kind": "email",
"email": "mara@example.com",
"role": "collaborator",
"days": 7
}
""";
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");#Responses
#201 Created
Created.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
object | string | yes | — | One of "invite". |
id | string | yes | — | |
project_id | string | yes | — | |
kind | string | yes | — | One of "email", "link". |
email | string | yes | — | The address it was sent to, while the invitation waits; null for a link, and null once it is accepted, declined, revoked or expired. May be null. |
role | string | yes | — | One of "admin", "collaborator", "viewer". |
state | string | yes | — | One of "pending", "accepted", "declined", "revoked", "expired". |
uses | integer | yes | — | 0 to …. |
uses_max | integer | yes | — | 1 to 50. May be null. |
invited_by | object | yes | — | Somebody as a project shows them: their membership's id while they are in it and the public Community profile they chose — never an account or an address. |
invited_by.member_id | string | yes | — | May be null. |
invited_by.name | string | yes | — | May be null. |
invited_by.handle | string | yes | — | May be null. |
invited_by.avatar_url | string | yes | — | A URL. May be null. |
invited_by.left | boolean | yes | — | Gone from the project since; what they wrote stays, with their name. |
created_at | string | yes | — | |
expires_at | string | yes | — | |
url | string | no | — | A link's address, in the answer that made it and never again: the token rides in its fragment, which no request carries to a server. A URL. |
request_id | string | no | — | Mirrored in the X-Request-Id header. |
Headers:
| Header | Description |
|---|---|
RateLimit-Limit | Burst capacity. |
RateLimit-Remaining | |
RateLimit-Reset | Seconds until refill. |
X-RateLimit-Limit | |
X-RateLimit-Remaining | |
X-RateLimit-Reset | Unix seconds. The X- spelling is what client libraries read. |
X-Request-Id |
#400 Bad Request
#401 Unauthorized
#403 Forbidden
#404 Not Found
#409 Conflict
#413 Payload Too Large
#429 Too Many Requests
#500 Internal Server Error
#503 Service Unavailable
#Status codes
| Status | Meaning |
|---|---|
201 | Created. |
400 | Bad Request |
401 | Unauthorized |
403 | Forbidden |
404 | Not Found |
409 | Conflict |
413 | Payload Too Large |
429 | Too Many Requests |
500 | Internal Server Error |
503 | Service Unavailable |
Every refusal names its code, and every code is explained at Errors.