curl --request POST \
--url https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"product_id": "1p-msp-us",
"contact_info": {
"email": "admin@acme-corp.com",
"company_name": "Acme Corporation"
},
"metadata": {
"one_password_domain": "acme-corp.1password.com"
}
}
'const url = 'https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link';
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
product_id: '1p-msp-us',
contact_info: {email: 'admin@acme-corp.com', company_name: 'Acme Corporation'},
metadata: {one_password_domain: 'acme-corp.1password.com'}
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));import requests
url = "https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link"
payload = {
"product_id": "1p-msp-us",
"contact_info": {
"email": "admin@acme-corp.com",
"company_name": "Acme Corporation"
},
"metadata": { "one_password_domain": "acme-corp.1password.com" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link"
payload := strings.NewReader("{\n \"product_id\": \"1p-msp-us\",\n \"contact_info\": {\n \"email\": \"admin@acme-corp.com\",\n \"company_name\": \"Acme Corporation\"\n },\n \"metadata\": {\n \"one_password_domain\": \"acme-corp.1password.com\"\n }\n}")
req, _ := http.NewRequest("POST", 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))
}using RestSharp;
var options = new RestClientOptions("https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("Authorization", "Bearer <token>");
request.AddJsonBody("{\n \"product_id\": \"1p-msp-us\",\n \"contact_info\": {\n \"email\": \"admin@acme-corp.com\",\n \"company_name\": \"Acme Corporation\"\n },\n \"metadata\": {\n \"one_password_domain\": \"acme-corp.1password.com\"\n }\n}", false);
var response = await client.PostAsync(request);
Console.WriteLine("{0}", response.Content);
HttpResponse<String> response = Unirest.post("https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"product_id\": \"1p-msp-us\",\n \"contact_info\": {\n \"email\": \"admin@acme-corp.com\",\n \"company_name\": \"Acme Corporation\"\n },\n \"metadata\": {\n \"one_password_domain\": \"acme-corp.1password.com\"\n }\n}")
.asString();<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'product_id' => '1p-msp-us',
'contact_info' => [
'email' => 'admin@acme-corp.com',
'company_name' => 'Acme Corporation'
],
'metadata' => [
'one_password_domain' => 'acme-corp.1password.com'
]
]),
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;
}$headers=@{}
$headers.Add("Authorization", "Bearer <token>")
$headers.Add("Content-Type", "application/json")
$response = Invoke-WebRequest -Uri 'https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link' -Method POST -Headers $headers -ContentType 'application/json' -Body '{
"product_id": "1p-msp-us",
"contact_info": {
"email": "admin@acme-corp.com",
"company_name": "Acme Corporation"
},
"metadata": {
"one_password_domain": "acme-corp.1password.com"
}
}'require 'uri'
require 'net/http'
url = URI("https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"product_id\": \"1p-msp-us\",\n \"contact_info\": {\n \"email\": \"admin@acme-corp.com\",\n \"company_name\": \"Acme Corporation\"\n },\n \"metadata\": {\n \"one_password_domain\": \"acme-corp.1password.com\"\n }\n}"
response = http.request(request)
puts response.read_body{
"entitlement": {
"path": "distributor-customers/cust_789xyz/entitlements/ent_link789abc",
"id": "ent_link789abc",
"customer_id": "cust_789xyz",
"product_id": "1p-msp-us",
"status": "pending",
"contact_info": {
"email": "admin@acme-corp.com",
"company_name": "Acme Corporation"
},
"create_time": "2026-09-15T10:30:00Z",
"expire_time": "2026-09-20T10:30:00Z"
}
}{
"code": "invalid_argument",
"message": "The 'email' field must be a valid email address."
}{
"code": "unauthenticated",
"message": "Authentication required. Please provide a valid bearer token."
}{
"code": "not_found",
"message": "The requested resource was not found."
}{
"code": "already_exists",
"message": "An entitlement for this product already exists."
}"Too Many Requests"{
"code": "internal",
"message": "An internal error occurred. Please try again later."
}Link an entitlement
Create a change-of-channel entitlement to link an existing 1Password account.
curl --request POST \
--url https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"product_id": "1p-msp-us",
"contact_info": {
"email": "admin@acme-corp.com",
"company_name": "Acme Corporation"
},
"metadata": {
"one_password_domain": "acme-corp.1password.com"
}
}
'const url = 'https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link';
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
product_id: '1p-msp-us',
contact_info: {email: 'admin@acme-corp.com', company_name: 'Acme Corporation'},
metadata: {one_password_domain: 'acme-corp.1password.com'}
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));import requests
url = "https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link"
payload = {
"product_id": "1p-msp-us",
"contact_info": {
"email": "admin@acme-corp.com",
"company_name": "Acme Corporation"
},
"metadata": { "one_password_domain": "acme-corp.1password.com" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link"
payload := strings.NewReader("{\n \"product_id\": \"1p-msp-us\",\n \"contact_info\": {\n \"email\": \"admin@acme-corp.com\",\n \"company_name\": \"Acme Corporation\"\n },\n \"metadata\": {\n \"one_password_domain\": \"acme-corp.1password.com\"\n }\n}")
req, _ := http.NewRequest("POST", 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))
}using RestSharp;
var options = new RestClientOptions("https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("Authorization", "Bearer <token>");
request.AddJsonBody("{\n \"product_id\": \"1p-msp-us\",\n \"contact_info\": {\n \"email\": \"admin@acme-corp.com\",\n \"company_name\": \"Acme Corporation\"\n },\n \"metadata\": {\n \"one_password_domain\": \"acme-corp.1password.com\"\n }\n}", false);
var response = await client.PostAsync(request);
Console.WriteLine("{0}", response.Content);
HttpResponse<String> response = Unirest.post("https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"product_id\": \"1p-msp-us\",\n \"contact_info\": {\n \"email\": \"admin@acme-corp.com\",\n \"company_name\": \"Acme Corporation\"\n },\n \"metadata\": {\n \"one_password_domain\": \"acme-corp.1password.com\"\n }\n}")
.asString();<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'product_id' => '1p-msp-us',
'contact_info' => [
'email' => 'admin@acme-corp.com',
'company_name' => 'Acme Corporation'
],
'metadata' => [
'one_password_domain' => 'acme-corp.1password.com'
]
]),
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;
}$headers=@{}
$headers.Add("Authorization", "Bearer <token>")
$headers.Add("Content-Type", "application/json")
$response = Invoke-WebRequest -Uri 'https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link' -Method POST -Headers $headers -ContentType 'application/json' -Body '{
"product_id": "1p-msp-us",
"contact_info": {
"email": "admin@acme-corp.com",
"company_name": "Acme Corporation"
},
"metadata": {
"one_password_domain": "acme-corp.1password.com"
}
}'require 'uri'
require 'net/http'
url = URI("https://api.1password.eu/v1/distributor-customers/{distributor-customer}/entitlements:link")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"product_id\": \"1p-msp-us\",\n \"contact_info\": {\n \"email\": \"admin@acme-corp.com\",\n \"company_name\": \"Acme Corporation\"\n },\n \"metadata\": {\n \"one_password_domain\": \"acme-corp.1password.com\"\n }\n}"
response = http.request(request)
puts response.read_body{
"entitlement": {
"path": "distributor-customers/cust_789xyz/entitlements/ent_link789abc",
"id": "ent_link789abc",
"customer_id": "cust_789xyz",
"product_id": "1p-msp-us",
"status": "pending",
"contact_info": {
"email": "admin@acme-corp.com",
"company_name": "Acme Corporation"
},
"create_time": "2026-09-15T10:30:00Z",
"expire_time": "2026-09-20T10:30:00Z"
}
}{
"code": "invalid_argument",
"message": "The 'email' field must be a valid email address."
}{
"code": "unauthenticated",
"message": "Authentication required. Please provide a valid bearer token."
}{
"code": "not_found",
"message": "The requested resource was not found."
}{
"code": "already_exists",
"message": "An entitlement for this product already exists."
}"Too Many Requests"{
"code": "internal",
"message": "An internal error occurred. Please try again later."
}acme-corp.1password.com), along with the product_id to provision and the customer’s contact_info.
Linking an entitlement works as follows:
- The entitlement is created with a status of
pendingand anexpire_time5 days from creation. - 1Password sends an email to the customer with their entitlement code. The email includes your distributor name and the product name.
- The customer claims the code for their existing 1Password account, which completes the link and transitions the entitlement to
active.
expired.409 error unless it has a cancelled or expired status.If the existing entitlement is cancelled or expired, it’s reactivated with a status of pending.A reactivated entitlement keeps its original id and create_time, with the contact details from the new request.Authorizations
Bearer token authentication. When a distributor is registered, they receive an opaque bearer token (prefixed op_b_). Include it in the Authorization header of every request as Bearer <token>.
Path Parameters
The customer ID, as defined in the distributor's own system.
Body
The request body for linking an existing 1Password account.
The ID of the 1Password product to provision.
1The customer details for account activation and setup.
Show child attributes
Show child attributes
The change of channel information. Required, and must include one_password_domain.
Show child attributes
Show child attributes
Response
The linked change of channel entitlement.
The response for a successful entitlement link.
The linked entitlement.
Show child attributes
Show child attributes
Was this page helpful?