curl --request PUT \
--url https://api.reply.io/v3/api-keys/{id}/scopes \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"scopes": [
"<string>"
]
}
'import requests
url = "https://api.reply.io/v3/api-keys/{id}/scopes"
payload = { "scopes": ["<string>"] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({scopes: ['<string>']})
};
fetch('https://api.reply.io/v3/api-keys/{id}/scopes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.reply.io/v3/api-keys/{id}/scopes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'scopes' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.reply.io/v3/api-keys/{id}/scopes"
payload := strings.NewReader("{\n \"scopes\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.reply.io/v3/api-keys/{id}/scopes")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"scopes\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reply.io/v3/api-keys/{id}/scopes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"scopes\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"type": "user",
"hint": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"scopes": [
"<string>"
],
"name": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}{
"title": "Bad Request",
"status": 400,
"detail": "'tasks:*' is not a scope this route can grant.",
"code": "apiKey.invalidScope"
}{
"title": "Unauthorized",
"status": 401,
"detail": "Authentication credentials are missing or invalid."
}{
"title": "Forbidden",
"status": 403,
"detail": "This API key does not hold 'inbox:read', so it cannot leave a key with it.",
"code": "apiKey.scopeNotHeld"
}{
"title": "Not Found",
"status": 404,
"detail": "API key not found.",
"code": "apiKey.notFound"
}{
"title": "Too Many Requests",
"status": 429,
"detail": "API calls quota exceeded! maximum admitted 100 per 1m."
}Set an API key's scopes
Coming soon. This endpoint will be available by mid November 2026.
api-keys:write scope (or a broader one that includes it).
Replace a key’s scopes. A scope already on the key stays valid here, even a wildcard; a new one must be an exact scope. An API key may set only scopes it holds, so it can cut a wider key down to what it holds itself. An API key that has an expiry cannot add a scope to a key that expires later or never.
A session token of an application other than Reply’s own is refused here. This bounds registered applications; it is not a credential check, since a public application’s identifier is not a secret.
curl --request PUT \
--url https://api.reply.io/v3/api-keys/{id}/scopes \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"scopes": [
"<string>"
]
}
'import requests
url = "https://api.reply.io/v3/api-keys/{id}/scopes"
payload = { "scopes": ["<string>"] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({scopes: ['<string>']})
};
fetch('https://api.reply.io/v3/api-keys/{id}/scopes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.reply.io/v3/api-keys/{id}/scopes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'scopes' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.reply.io/v3/api-keys/{id}/scopes"
payload := strings.NewReader("{\n \"scopes\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.reply.io/v3/api-keys/{id}/scopes")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"scopes\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reply.io/v3/api-keys/{id}/scopes")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"scopes\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"type": "user",
"hint": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"scopes": [
"<string>"
],
"name": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}{
"title": "Bad Request",
"status": 400,
"detail": "'tasks:*' is not a scope this route can grant.",
"code": "apiKey.invalidScope"
}{
"title": "Unauthorized",
"status": 401,
"detail": "Authentication credentials are missing or invalid."
}{
"title": "Forbidden",
"status": 403,
"detail": "This API key does not hold 'inbox:read', so it cannot leave a key with it.",
"code": "apiKey.scopeNotHeld"
}{
"title": "Not Found",
"status": 404,
"detail": "API key not found.",
"code": "apiKey.notFound"
}{
"title": "Too Many Requests",
"status": 429,
"detail": "API calls quota exceeded! maximum admitted 100 per 1m."
}Authorizations
Authenticate every request with a Bearer token. Pass your Reply API key in the
Authorization header:
Authorization: Bearer <your-api-key>
Get your API key from the Reply dashboard: Settings → API Key.
Path Parameters
The key's id.
Body
The scopes the key ends with.
Response
The key as it now stands.
The key's id.
Who the key belongs to.
user, team, organization The start and end of the key, as Settings shows it.
When the key was created.
The scopes as stored, which may include wildcards set in Settings.
The key's name.
When the key stops working, or null if it never does.