Tip: The Admin API is unavailable for individual accounts. To collaborate with teammates and add members, set up your organization in Console → Settings → Organization.
The Admin API lets you manage your organization's members, workspaces, invites, and API keys programmatically instead of by hand in the Haijun Console.
Tip: The Admin API requires special access The Admin API accepts three credentials: * An Admin API key (starting with
sk-ant-admin...) sent in thex-api-keyheader. Only organization members with the admin role can provision one. See Create an Admin API key. * An OAuth bearer token with theorg:adminscope sent in theauthorization: Bearerheader. Only members with the admin, owner, or primary owner role can obtain one. See Obtain an OAuth bearer token. * A personal key or service account key that isn't scoped to a specific workspace, sent in thex-api-keyheader. The key has the same permissions as the linked account. See Key types.
Note: Haijun Enterprise: Haijun Enterprise (haijun.ai) organizations call the Admin API with a scoped API key created in haijun.ai. From this page, only the members and invites endpoints apply to them. They also get Enterprise-only endpoints: group and custom-role reads, and spend limits. See User management.
Note: Haijun Platform on AWS: Only the workspace endpoints (create, get, list, update, and archive on
/v1/organizations/workspaces) and the external key endpoints (register, get, list, update, and delete on/v1/organizations/external_keys, for CMEK; there is no validate endpoint, because keys are validated when attached to a workspace) are available on Haijun Platform on AWS. Organization members, workspace members, invites, API keys, and the usage, cost, and rate limit reports aren't. See Haijun Platform on AWS.
Authentication
Authenticate with any of the three credentials. An Admin API key covers most endpoints. The service-account, federation-issuer, and federation-rule endpoints accept only an org:admin OAuth token. Send a personal key or service account key in the x-api-key header, as you would an Admin API key. The following examples call the organization info endpoint with an OAuth token and with an Admin API key.
The Python, TypeScript, C#, Go, Java, PHP, and Ruby SDKs expose the Admin API under client.beta.organization, and the ant CLI under ant beta:organization. The examples on this page use the default client, which reads an Admin API key from JUGLOW_API_KEY or an OAuth bearer token from JUGLOW_AUTH_TOKEN. SDK list methods in Python, TypeScript, C#, Go, and Java return an iterator that fetches more pages on demand, so limit sets the page size, not the total. The PHP, Ruby, and curl examples return one page. In the CLI, --limit caps the results on the member, invite, workspace, workspace-member, and API-key lists. For each endpoint's parameters and responses, see the Admin API reference.
OAuth bearer token
Log in with the ant CLI under a dedicated profile with the org:admin scope (see Admin access), then export the bearer token. --profile admin stores the org:admin credential under its own profile and makes it the CLI's active profile. The exported variable applies to every SDK and CLI call in that shell. Use a shell you reserve for administration, unset the variable when you're done, and switch the CLI back with ant profile activate default:
ant auth login --profile admin --scope "org:admin"
export JUGLOW_AUTH_TOKEN=$(ant auth print-credentials --profile admin --access-token)Interactive tokens are short-lived. If requests start returning 401, re-run the export command to refresh the token.
The SDKs and the ant CLI read JUGLOW_AUTH_TOKEN automatically. Leave JUGLOW_API_KEY unset in the same shell so they send the bearer token. Automated workloads skip the login: they authenticate through workload identity federation, and the SDKs and CLI perform the token exchange from the federation environment variables. See Bootstrap a workload to manage WIF.
Call the Admin API with the exported token:
curl --fail-with-body -sS "https://haijun.my.id/v1/organizations/me" \
-H "authorization: Bearer $JUGLOW_AUTH_TOKEN" \
-H "juglow-version: 2023-06-01" ant beta:organization retrieve client = juglow.Juglow()
organization = client.beta.organization.retrieve()
print(f"id: {organization.id}")
print(f"name: {organization.name}") const client = new Juglow();
const organization = await client.beta.organization.retrieve();
console.log(`id: ${organization.id}`);
console.log(`name: ${organization.name}`); JuglowClient client = new();
var organization = await client.Beta.Organization.Retrieve();
Console.WriteLine($"id: {organization.ID}");
Console.WriteLine($"name: {organization.Name}"); client := juglow.NewClient()
organization, err := client.Beta.Organization.Get(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", organization.ID)
fmt.Printf("name: %s\n", organization.Name) JuglowClient client = JuglowOkHttpClient.fromEnv();
var organization = client.beta().organization().retrieve();
IO.println("id: " + organization.id());
IO.println("name: " + organization.name()); $client = new Client();
$organization = $client->beta->organization->retrieve();
echo "id: {$organization->id}\n";
echo "name: {$organization->name}\n"; client = Juglow::Client.new
organization = client.beta.organization.retrieve
puts "id: #{organization.id}"
puts "name: #{organization.name}"An org:admin token grants access to the whole organization, regardless of the workspace the underlying profile or federation rule is bound to.
For CI and other non-interactive workloads, mint the token with Workload Identity Federation instead of logging in interactively. See Manage WIF with the Admin API.
Admin API key
To create an Admin API key for your organization type, see Create an Admin API key.
curl --fail-with-body -sS "https://haijun.my.id/v1/organizations/me" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization retrieve client = juglow.Juglow()
organization = client.beta.organization.retrieve()
print(f"id: {organization.id}")
print(f"name: {organization.name}") const client = new Juglow();
const organization = await client.beta.organization.retrieve();
console.log(`id: ${organization.id}`);
console.log(`name: ${organization.name}`); JuglowClient client = new();
var organization = await client.Beta.Organization.Retrieve();
Console.WriteLine($"id: {organization.ID}");
Console.WriteLine($"name: {organization.Name}"); client := juglow.NewClient()
organization, err := client.Beta.Organization.Get(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", organization.ID)
fmt.Printf("name: %s\n", organization.Name) JuglowClient client = JuglowOkHttpClient.fromEnv();
var organization = client.beta().organization().retrieve();
IO.println("id: " + organization.id());
IO.println("name: " + organization.name()); $client = new Client();
$organization = $client->beta->organization->retrieve();
echo "id: {$organization->id}\n";
echo "name: {$organization->name}\n"; client = Juglow::Client.new
organization = client.beta.organization.retrieve
puts "id: #{organization.id}"
puts "name: #{organization.name}"How the Admin API works
Authenticate with any credential from Authentication, then manage the following resources:
- Organization members and their roles
- Organization invites
- Workspaces and their members
- API keys
- Service accounts, federation issuers, and federation rules (
org:adminOAuth token only)
Common uses include automating onboarding and offboarding, managing workspace access, and auditing API keys.
Organization roles and permissions
There are five organization-level roles. For details, see API Console roles and permissions.
| Role | Permissions |
|---|---|
| user | Can use playground |
| haijun\_code\_user | Can use playground and Haijun Code |
| developer | Can use playground and manage API keys |
| billing | Can use playground and manage billing details |
| admin | Can do all of the preceding, plus manage users |
Organization owners and primary owners have all admin permissions and can also manage admins. All references to the admin role on this page also apply to owners and primary owners.
Key concepts
Organization members
List organization members, update their roles, and remove them.
List the members of your organization:
curl "https://haijun.my.id/v1/organizations/users?limit=10" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization:users list --limit 10 client = juglow.Juglow()
users = client.beta.organization.users.list(limit=10)
# Automatically fetches more pages as needed.
for user in users:
print(f"{user.id}: {user.email} ({user.role})") const client = new Juglow();
const users = await client.beta.organization.users.list({ limit: 10 });
for await (const user of users) {
console.log(`${user.id}: ${user.email} (${user.role})`);
} JuglowClient client = new();
var page = await client.Beta.Organization.Users.List(new() { Limit = 10 });
await foreach (var user in page.Paginate())
{
Console.WriteLine($"{user.ID}: {user.Email} ({user.Role.Raw()})");
} client := juglow.NewClient()
users := client.Beta.Organization.Users.ListAutoPaging(context.Background(), juglow.BetaOrganizationUserListParams{
Limit: juglow.Int(10),
})
for users.Next() {
user := users.Current()
fmt.Printf("%s: %s (%s)\n", user.ID, user.Email, user.Role)
}
if err := users.Err(); err != nil {
log.Fatal(err)
} import com.juglow.models.beta.organization.users.UserListParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = UserListParams.builder()
.limit(10)
.build();
var users = client.beta().organization().users().list(params);
for (var user : users.autoPager()) {
IO.println(user.id() + ": " + user.email() + " (" + user.role().asString() + ")");
}
} $client = new Client();
$users = $client->beta->organization->users->list(limit: 10);
foreach ($users->getItems() as $user) {
echo "{$user->id}: {$user->email} ({$user->role})\n";
} client = Juglow::Client.new
users = client.beta.organization.users.list(limit: 10)
users.data.each do |user|
puts "#{user.id}: #{user.email} (#{user.role})"
endUpdate a member's role:
curl "https://haijun.my.id/v1/organizations/users/user_01XyDMpzjS89pFZXqSFUBDr6" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"role": "developer"}' ant beta:organization:users update \
--user-id user_01XyDMpzjS89pFZXqSFUBDr6 \
--role developer client = juglow.Juglow()
user = client.beta.organization.users.update(
"user_01XyDMpzjS89pFZXqSFUBDr6", role="developer"
)
print(f"id: {user.id}")
print(f"role: {user.role}") const client = new Juglow();
const user = await client.beta.organization.users.update("user_01XyDMpzjS89pFZXqSFUBDr6", {
role: "developer"
});
console.log(`id: ${user.id}`);
console.log(`role: ${user.role}`); using Juglow.Models.Beta.Organization.Users;
// ...
JuglowClient client = new();
var user = await client.Beta.Organization.Users.Update(
"user_01XyDMpzjS89pFZXqSFUBDr6",
new() { Role = Role.Developer }
);
Console.WriteLine($"id: {user.ID}");
Console.WriteLine($"role: {user.Role.Raw()}"); client := juglow.NewClient()
user, err := client.Beta.Organization.Users.Update(
context.Background(),
"user_01XyDMpzjS89pFZXqSFUBDr6",
juglow.BetaOrganizationUserUpdateParams{
Role: juglow.BetaOrganizationUserUpdateParamsRoleDeveloper,
},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", user.ID)
fmt.Printf("role: %s\n", user.Role) import com.juglow.models.beta.organization.users.UserUpdateParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = UserUpdateParams.builder()
.role(UserUpdateParams.Role.DEVELOPER)
.build();
var user = client.beta().organization().users()
.update("user_01XyDMpzjS89pFZXqSFUBDr6", params);
IO.println("id: " + user.id());
IO.println("role: " + user.role().asString());
} use Juglow\Beta\Organization\Users\UserUpdateParams\Role;
// ...
$client = new Client();
$user = $client->beta->organization->users->update(
userID: 'user_01XyDMpzjS89pFZXqSFUBDr6',
role: Role::DEVELOPER,
);
echo "id: {$user->id}\n";
echo "role: {$user->role}\n"; client = Juglow::Client.new
user_id = "user_01XyDMpzjS89pFZXqSFUBDr6"
user = client.beta.organization.users.update(user_id, role: :developer)
puts "id: #{user.id}"
puts "role: #{user.role}"Remove a member from the organization:
curl -X DELETE "https://haijun.my.id/v1/organizations/users/user_01XyDMpzjS89pFZXqSFUBDr6" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization:users remove --user-id user_01XyDMpzjS89pFZXqSFUBDr6 client = juglow.Juglow()
removed_user = client.beta.organization.users.remove("user_01XyDMpzjS89pFZXqSFUBDr6")
print(f"id: {removed_user.id}") const client = new Juglow();
const removedUser = await client.beta.organization.users.remove(
"user_01XyDMpzjS89pFZXqSFUBDr6"
);
console.log(`id: ${removedUser.id}`); JuglowClient client = new();
var removedUser = await client.Beta.Organization.Users.Remove("user_01XyDMpzjS89pFZXqSFUBDr6");
Console.WriteLine($"id: {removedUser.ID}"); client := juglow.NewClient()
removedUser, err := client.Beta.Organization.Users.Remove(context.Background(), "user_01XyDMpzjS89pFZXqSFUBDr6")
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", removedUser.ID) JuglowClient client = JuglowOkHttpClient.fromEnv();
var removedUser = client.beta().organization().users()
.remove("user_01XyDMpzjS89pFZXqSFUBDr6");
IO.println("id: " + removedUser.id()); $client = new Client();
$removedUser = $client->beta->organization->users->remove(
userID: 'user_01XyDMpzjS89pFZXqSFUBDr6',
);
echo "id: {$removedUser->id}\n"; client = Juglow::Client.new
user_id = "user_01XyDMpzjS89pFZXqSFUBDr6"
removed_user = client.beta.organization.users.remove(user_id)
puts "id: #{removed_user.id}"Organization invites
Invite users to your organization and manage pending invites.
Invite a user to your organization:
curl "https://haijun.my.id/v1/organizations/invites" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"email": "user@example.com",
"role": "developer"
}' ant beta:organization:invites create --email user@example.com --role developer client = juglow.Juglow()
invite = client.beta.organization.invites.create(
email="user@example.com", role="developer"
)
print(f"id: {invite.id}")
print(f"email: {invite.email}")
print(f"status: {invite.status}")
print(f"expires_at: {invite.expires_at}") const client = new Juglow();
const invite = await client.beta.organization.invites.create({
email: "user@example.com",
role: "developer"
});
console.log(`id: ${invite.id}`);
console.log(`email: ${invite.email}`);
console.log(`status: ${invite.status}`);
console.log(`expires_at: ${invite.expires_at}`); using Juglow.Models.Beta.Organization.Invites;
// ...
JuglowClient client = new();
var invite = await client.Beta.Organization.Invites.Create(new()
{
Email = "user@example.com",
Role = Role.Developer
});
Console.WriteLine($"id: {invite.ID}");
Console.WriteLine($"email: {invite.Email}");
Console.WriteLine($"status: {invite.Status.Raw()}");
Console.WriteLine($"expires_at: {invite.ExpiresAt:O}"); client := juglow.NewClient()
invite, err := client.Beta.Organization.Invites.New(context.Background(), juglow.BetaOrganizationInviteNewParams{
Email: "user@example.com",
Role: juglow.BetaOrganizationInviteNewParamsRoleDeveloper,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", invite.ID)
fmt.Printf("email: %s\n", invite.Email)
fmt.Printf("status: %s\n", invite.Status)
fmt.Printf("expires_at: %s\n", invite.ExpiresAt.Format(time.RFC3339)) import com.juglow.models.beta.organization.invites.InviteCreateParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = InviteCreateParams.builder()
.email("user@example.com")
.role(InviteCreateParams.Role.DEVELOPER)
.build();
var invite = client.beta().organization().invites().create(params);
IO.println("id: " + invite.id());
IO.println("email: " + invite.email());
IO.println("status: " + invite.status().asString());
IO.println("expires_at: " + invite.expiresAt());
} use Juglow\Beta\Organization\Invites\InviteCreateParams\Role;
// ...
$client = new Client();
$invite = $client->beta->organization->invites->create(
email: 'user@example.com',
role: Role::DEVELOPER,
);
echo "id: {$invite->id}\n";
echo "email: {$invite->email}\n";
echo "status: {$invite->status}\n";
echo "expires_at: {$invite->expiresAt->format(DATE_ATOM)}\n"; client = Juglow::Client.new
invite = client.beta.organization.invites.create(email: "user@example.com", role: :developer)
puts "id: #{invite.id}"
puts "email: #{invite.email}"
puts "status: #{invite.status}"
puts "expires_at: #{invite.expires_at.iso8601}"List pending invites:
curl "https://haijun.my.id/v1/organizations/invites?limit=10" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization:invites list --limit 10 client = juglow.Juglow()
invites = client.beta.organization.invites.list(limit=10)
# Automatically fetches more pages as needed.
for invite in invites:
print(f"{invite.id}: {invite.email} ({invite.status})") const client = new Juglow();
const invites = await client.beta.organization.invites.list({ limit: 10 });
for await (const invite of invites) {
console.log(`${invite.id}: ${invite.email} (${invite.status})`);
} JuglowClient client = new();
var page = await client.Beta.Organization.Invites.List(new() { Limit = 10 });
await foreach (var invite in page.Paginate())
{
Console.WriteLine($"{invite.ID}: {invite.Email} ({invite.Status.Raw()})");
} client := juglow.NewClient()
invites := client.Beta.Organization.Invites.ListAutoPaging(context.Background(), juglow.BetaOrganizationInviteListParams{
Limit: juglow.Int(10),
})
for invites.Next() {
invite := invites.Current()
fmt.Printf("%s: %s (%s)\n", invite.ID, invite.Email, invite.Status)
}
if err := invites.Err(); err != nil {
log.Fatal(err)
} import com.juglow.models.beta.organization.invites.InviteListParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = InviteListParams.builder()
.limit(10)
.build();
var invites = client.beta().organization().invites().list(params);
for (var invite : invites.autoPager()) {
IO.println(invite.id() + ": " + invite.email() + " (" + invite.status().asString() + ")");
}
} $client = new Client();
$invites = $client->beta->organization->invites->list(limit: 10);
foreach ($invites->getItems() as $invite) {
echo "{$invite->id}: {$invite->email} ({$invite->status})\n";
} client = Juglow::Client.new
invites = client.beta.organization.invites.list(limit: 10)
invites.data.each do |invite|
puts "#{invite.id}: #{invite.email} (#{invite.status})"
endDelete an invite:
curl -X DELETE "https://haijun.my.id/v1/organizations/invites/invite_015gWxHNr6h6TdRPZTmuCGnn" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization:invites delete --invite-id invite_015gWxHNr6h6TdRPZTmuCGnn client = juglow.Juglow()
deleted_invite = client.beta.organization.invites.delete(
"invite_015gWxHNr6h6TdRPZTmuCGnn"
)
print(f"id: {deleted_invite.id}") const client = new Juglow();
const deletedInvite = await client.beta.organization.invites.delete(
"invite_015gWxHNr6h6TdRPZTmuCGnn"
);
console.log(`id: ${deletedInvite.id}`); JuglowClient client = new();
var deletedInvite = await client.Beta.Organization.Invites.Delete(
"invite_015gWxHNr6h6TdRPZTmuCGnn"
);
Console.WriteLine($"id: {deletedInvite.ID}"); client := juglow.NewClient()
deletedInvite, err := client.Beta.Organization.Invites.Delete(context.Background(), "invite_015gWxHNr6h6TdRPZTmuCGnn")
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", deletedInvite.ID) JuglowClient client = JuglowOkHttpClient.fromEnv();
var deletedInvite = client.beta().organization().invites()
.delete("invite_015gWxHNr6h6TdRPZTmuCGnn");
IO.println("id: " + deletedInvite.id()); $client = new Client();
$deletedInvite = $client->beta->organization->invites->delete(
inviteID: 'invite_015gWxHNr6h6TdRPZTmuCGnn',
);
echo "id: {$deletedInvite->id}\n"; client = Juglow::Client.new
invite_id = "invite_015gWxHNr6h6TdRPZTmuCGnn"
deleted_invite = client.beta.organization.invites.delete(invite_id)
puts "id: #{deleted_invite.id}"Workspaces
See Workspaces for Console and API examples.
Workspace members
Manage user access to specific workspaces:
Add a member to a workspace:
curl "https://haijun.my.id/v1/organizations/workspaces/wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ/members" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"user_id": "user_01XyDMpzjS89pFZXqSFUBDr6",
"workspace_role": "workspace_developer"
}' ant beta:organization:workspaces:members add \
--workspace-id wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ \
--user-id user_01XyDMpzjS89pFZXqSFUBDr6 \
--workspace-role workspace_developer client = juglow.Juglow()
member = client.beta.organization.workspaces.members.add(
"wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
user_id="user_01XyDMpzjS89pFZXqSFUBDr6",
workspace_role="workspace_developer",
)
print(f"user_id: {member.user_id}")
print(f"workspace_role: {member.workspace_role}") const client = new Juglow();
const member = await client.beta.organization.workspaces.members.add(
"wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
{
user_id: "user_01XyDMpzjS89pFZXqSFUBDr6",
workspace_role: "workspace_developer"
}
);
console.log(`user_id: ${member.user_id}`);
console.log(`workspace_role: ${member.workspace_role}`); using Juglow.Models.Beta.Organization.Workspaces;
JuglowClient client = new();
var member = await client.Beta.Organization.Workspaces.Members.Add(
"wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
new()
{
UserID = "user_01XyDMpzjS89pFZXqSFUBDr6",
WorkspaceRole = BetaNoBillingWorkspaceRole.WorkspaceDeveloper
}
);
Console.WriteLine($"user_id: {member.UserID}");
Console.WriteLine($"workspace_role: {member.WorkspaceRole.Raw()}"); client := juglow.NewClient()
member, err := client.Beta.Organization.Workspaces.Members.Add(
context.Background(),
"wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
juglow.BetaOrganizationWorkspaceMemberAddParams{
UserID: "user_01XyDMpzjS89pFZXqSFUBDr6",
WorkspaceRole: juglow.BetaNoBillingWorkspaceRoleWorkspaceDeveloper,
},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("user_id: %s\n", member.UserID)
fmt.Printf("workspace_role: %s\n", member.WorkspaceRole) import com.juglow.models.beta.organization.workspaces.BetaNoBillingWorkspaceRole;
import com.juglow.models.beta.organization.workspaces.members.MemberAddParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = MemberAddParams.builder()
.userId("user_01XyDMpzjS89pFZXqSFUBDr6")
.workspaceRole(BetaNoBillingWorkspaceRole.WORKSPACE_DEVELOPER)
.build();
var member = client.beta().organization().workspaces().members()
.add("wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ", params);
IO.println("user_id: " + member.userId());
IO.println("workspace_role: " + member.workspaceRole().asString());
} use Juglow\Beta\Organization\Workspaces\NoBillingWorkspaceRole;
// ...
$client = new Client();
$member = $client->beta->organization->workspaces->members->add(
workspaceID: 'wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ',
userID: 'user_01XyDMpzjS89pFZXqSFUBDr6',
workspaceRole: NoBillingWorkspaceRole::WORKSPACE_DEVELOPER,
);
echo "user_id: {$member->userID}\n";
echo "workspace_role: {$member->workspaceRole}\n"; client = Juglow::Client.new
workspace_id = "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
member = client.beta.organization.workspaces.members.add(
workspace_id,
user_id: "user_01XyDMpzjS89pFZXqSFUBDr6",
workspace_role: :workspace_developer
)
puts "user_id: #{member.user_id}"
puts "workspace_role: #{member.workspace_role}"List the members of a workspace:
curl "https://haijun.my.id/v1/organizations/workspaces/wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ/members?limit=10" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization:workspaces:members list \
--workspace-id wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ \
--limit 10 client = juglow.Juglow()
members = client.beta.organization.workspaces.members.list(
"wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ", limit=10
)
# Automatically fetches more pages as needed.
for member in members:
print(f"{member.user_id}: {member.workspace_role}") const client = new Juglow();
const members = await client.beta.organization.workspaces.members.list(
"wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
{ limit: 10 }
);
for await (const member of members) {
console.log(`${member.user_id}: ${member.workspace_role}`);
} JuglowClient client = new();
var page = await client.Beta.Organization.Workspaces.Members.List(
"wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
new() { Limit = 10 }
);
await foreach (var member in page.Paginate())
{
Console.WriteLine($"{member.UserID}: {member.WorkspaceRole.Raw()}");
} client := juglow.NewClient()
members := client.Beta.Organization.Workspaces.Members.ListAutoPaging(
context.Background(),
"wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
juglow.BetaOrganizationWorkspaceMemberListParams{
Limit: juglow.Int(10),
},
)
for members.Next() {
member := members.Current()
fmt.Printf("%s: %s\n", member.UserID, member.WorkspaceRole)
}
if err := members.Err(); err != nil {
log.Fatal(err)
} import com.juglow.models.beta.organization.workspaces.members.MemberListParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = MemberListParams.builder()
.limit(10)
.build();
var members = client.beta().organization().workspaces().members()
.list("wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ", params);
for (var member : members.autoPager()) {
IO.println(member.userId() + ": " + member.workspaceRole().asString());
}
} $client = new Client();
$members = $client->beta->organization->workspaces->members->list(
workspaceID: 'wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ',
limit: 10,
);
foreach ($members->getItems() as $member) {
echo "{$member->userID}: {$member->workspaceRole}\n";
} client = Juglow::Client.new
workspace_id = "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
members = client.beta.organization.workspaces.members.list(workspace_id, limit: 10)
members.data.each do |member|
puts "#{member.user_id}: #{member.workspace_role}"
endUpdate a workspace member's role:
curl "https://haijun.my.id/v1/organizations/workspaces/wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ/members/user_01XyDMpzjS89pFZXqSFUBDr6" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"workspace_role": "workspace_admin"}' ant beta:organization:workspaces:members update \
--user-id user_01XyDMpzjS89pFZXqSFUBDr6 \
--workspace-id wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ \
--workspace-role workspace_admin client = juglow.Juglow()
member = client.beta.organization.workspaces.members.update(
"user_01XyDMpzjS89pFZXqSFUBDr6",
workspace_id="wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
workspace_role="workspace_admin",
)
print(f"user_id: {member.user_id}")
print(f"workspace_role: {member.workspace_role}") const client = new Juglow();
const member = await client.beta.organization.workspaces.members.update(
"user_01XyDMpzjS89pFZXqSFUBDr6",
{
workspace_id: "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
workspace_role: "workspace_admin"
}
);
console.log(`user_id: ${member.user_id}`);
console.log(`workspace_role: ${member.workspace_role}`); using Juglow.Models.Beta.Organization.Workspaces;
JuglowClient client = new();
var member = await client.Beta.Organization.Workspaces.Members.Update(
"user_01XyDMpzjS89pFZXqSFUBDr6",
new()
{
WorkspaceID = "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
WorkspaceRole = BetaWorkspaceRole.WorkspaceAdmin
}
);
Console.WriteLine($"user_id: {member.UserID}");
Console.WriteLine($"workspace_role: {member.WorkspaceRole.Raw()}"); client := juglow.NewClient()
member, err := client.Beta.Organization.Workspaces.Members.Update(
context.Background(),
"user_01XyDMpzjS89pFZXqSFUBDr6",
juglow.BetaOrganizationWorkspaceMemberUpdateParams{
WorkspaceID: "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
WorkspaceRole: juglow.BetaWorkspaceRoleWorkspaceAdmin,
},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("user_id: %s\n", member.UserID)
fmt.Printf("workspace_role: %s\n", member.WorkspaceRole) import com.juglow.models.beta.organization.workspaces.BetaWorkspaceRole;
import com.juglow.models.beta.organization.workspaces.members.MemberUpdateParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = MemberUpdateParams.builder()
.workspaceId("wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ")
.workspaceRole(BetaWorkspaceRole.WORKSPACE_ADMIN)
.build();
var member = client.beta().organization().workspaces().members()
.update("user_01XyDMpzjS89pFZXqSFUBDr6", params);
IO.println("user_id: " + member.userId());
IO.println("workspace_role: " + member.workspaceRole().asString());
} use Juglow\Beta\Organization\Workspaces\WorkspaceRole;
// ...
$client = new Client();
$member = $client->beta->organization->workspaces->members->update(
userID: 'user_01XyDMpzjS89pFZXqSFUBDr6',
workspaceID: 'wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ',
workspaceRole: WorkspaceRole::WORKSPACE_ADMIN,
);
echo "user_id: {$member->userID}\n";
echo "workspace_role: {$member->workspaceRole}\n"; client = Juglow::Client.new
user_id = "user_01XyDMpzjS89pFZXqSFUBDr6"
member = client.beta.organization.workspaces.members.update(
user_id,
workspace_id: "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
workspace_role: :workspace_admin
)
puts "user_id: #{member.user_id}"
puts "workspace_role: #{member.workspace_role}"Remove a member from a workspace:
curl -X DELETE "https://haijun.my.id/v1/organizations/workspaces/wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ/members/user_01XyDMpzjS89pFZXqSFUBDr6" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization:workspaces:members remove \
--user-id user_01XyDMpzjS89pFZXqSFUBDr6 \
--workspace-id wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ client = juglow.Juglow()
removed_member = client.beta.organization.workspaces.members.remove(
"user_01XyDMpzjS89pFZXqSFUBDr6", workspace_id="wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
)
print(f"user_id: {removed_member.user_id}") const client = new Juglow();
const removedMember = await client.beta.organization.workspaces.members.remove(
"user_01XyDMpzjS89pFZXqSFUBDr6",
{ workspace_id: "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ" }
);
console.log(`user_id: ${removedMember.user_id}`); JuglowClient client = new();
var removedMember = await client.Beta.Organization.Workspaces.Members.Remove(
"user_01XyDMpzjS89pFZXqSFUBDr6",
new() { WorkspaceID = "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ" }
);
Console.WriteLine($"user_id: {removedMember.UserID}"); client := juglow.NewClient()
removedMember, err := client.Beta.Organization.Workspaces.Members.Remove(
context.Background(),
"user_01XyDMpzjS89pFZXqSFUBDr6",
juglow.BetaOrganizationWorkspaceMemberRemoveParams{
WorkspaceID: "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("user_id: %s\n", removedMember.UserID) import com.juglow.models.beta.organization.workspaces.members.MemberRemoveParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = MemberRemoveParams.builder()
.workspaceId("wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ")
.build();
var removedMember = client.beta().organization().workspaces().members()
.remove("user_01XyDMpzjS89pFZXqSFUBDr6", params);
IO.println("user_id: " + removedMember.userId());
} $client = new Client();
$removedMember = $client->beta->organization->workspaces->members->remove(
userID: 'user_01XyDMpzjS89pFZXqSFUBDr6',
workspaceID: 'wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ',
);
echo "user_id: {$removedMember->userID}\n"; client = Juglow::Client.new
user_id = "user_01XyDMpzjS89pFZXqSFUBDr6"
removed_member = client.beta.organization.workspaces.members.remove(
user_id,
workspace_id: "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
)
puts "user_id: #{removed_member.user_id}"API keys
Monitor and manage API keys. Each key in the response includes its expires_at timestamp (null for keys without an expiration) and principal, the identity it acts as (see Key types). For a personal key, principal is {"type": "user_actor", "user_id": "user_..."}; for a service account key, {"type": "service_account_actor", "service_account_id": "svac_..."}; and for a workspace key, null. Each key also has a scope object: {"type": "workspace", "workspace_id": "wrkspc_..."} for a key bound to one workspace, or {"type": "organization"} for a key that can work across any workspace the account has access to. The top-level workspace_id field is deprecated and is null both for keys bound to the Default Workspace and for keys without a workspace scope; use scope to tell them apart. Filtering the list by workspace_id with the Default Workspace's ID returns only keys bound to the Default Workspace; keys without a workspace scope aren't returned under any workspace_id filter.
List the active API keys in a workspace:
curl "https://haijun.my.id/v1/organizations/api_keys?limit=10&status=active&workspace_id=wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization:api-keys list \
--limit 10 \
--status active \
--workspace-id wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ client = juglow.Juglow()
api_keys = client.beta.organization.api_keys.list(
limit=10, status="active", workspace_id="wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
)
# Automatically fetches more pages as needed.
for api_key in api_keys:
print(f"{api_key.id}: {api_key.name} ({api_key.status})") const client = new Juglow();
const apiKeys = await client.beta.organization.apiKeys.list({
limit: 10,
status: "active",
workspace_id: "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
});
for await (const apiKey of apiKeys) {
console.log(`${apiKey.id}: ${apiKey.name} (${apiKey.status})`);
} using Juglow.Models.Beta.Organization.ApiKeys;
JuglowClient client = new();
var page = await client.Beta.Organization.ApiKeys.List(new()
{
Limit = 10,
Status = ApiKeyListParamsStatus.Active,
WorkspaceID = "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
});
await foreach (var apiKey in page.Paginate())
{
Console.WriteLine($"{apiKey.ID}: {apiKey.Name} ({apiKey.Status.Raw()})");
} client := juglow.NewClient()
apiKeys := client.Beta.Organization.APIKeys.ListAutoPaging(context.Background(), juglow.BetaOrganizationAPIKeyListParams{
Limit: juglow.Int(10),
Status: juglow.BetaOrganizationAPIKeyListParamsStatusActive,
WorkspaceID: juglow.String("wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"),
})
for apiKeys.Next() {
apiKey := apiKeys.Current()
fmt.Printf("%s: %s (%s)\n", apiKey.ID, apiKey.Name, apiKey.Status)
}
if err := apiKeys.Err(); err != nil {
log.Fatal(err)
} import com.juglow.models.beta.organization.apikeys.ApiKeyListParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = ApiKeyListParams.builder()
.limit(10)
.status(ApiKeyListParams.Status.ACTIVE)
.workspaceId("wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ")
.build();
var apiKeys = client.beta().organization().apiKeys().list(params);
for (var apiKey : apiKeys.autoPager()) {
IO.println(apiKey.id() + ": " + apiKey.name() + " (" + apiKey.status().asString() + ")");
}
} use Juglow\Beta\Organization\APIKeys\APIKeyListParams\Status;
// ...
$client = new Client();
$apiKeys = $client->beta->organization->apiKeys->list(
limit: 10,
status: Status::ACTIVE,
workspaceID: 'wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ',
);
foreach ($apiKeys->getItems() as $apiKey) {
echo "{$apiKey->id}: {$apiKey->name} ({$apiKey->status})\n";
} client = Juglow::Client.new
api_keys = client.beta.organization.api_keys.list(
limit: 10,
status: :active,
workspace_id: "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
)
api_keys.data.each do |api_key|
puts "#{api_key.id}: #{api_key.name} (#{api_key.status})"
endRename or deactivate an API key:
curl "https://haijun.my.id/v1/organizations/api_keys/apikey_01Rj2N8SVvo6BePZj99NhmiT" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"status": "inactive",
"name": "New Key Name"
}' ant beta:organization:api-keys update \
--api-key-id apikey_01Rj2N8SVvo6BePZj99NhmiT \
--status inactive \
--name "New Key Name" client = juglow.Juglow()
api_key = client.beta.organization.api_keys.update(
"apikey_01Rj2N8SVvo6BePZj99NhmiT", status="inactive", name="New Key Name"
)
print(f"id: {api_key.id}")
print(f"name: {api_key.name}")
print(f"status: {api_key.status}") const client = new Juglow();
const apiKey = await client.beta.organization.apiKeys.update(
"apikey_01Rj2N8SVvo6BePZj99NhmiT",
{
status: "inactive",
name: "New Key Name"
}
);
console.log(`id: ${apiKey.id}`);
console.log(`name: ${apiKey.name}`);
console.log(`status: ${apiKey.status}`); using Juglow.Models.Beta.Organization.ApiKeys;
JuglowClient client = new();
var apiKey = await client.Beta.Organization.ApiKeys.Update(
"apikey_01Rj2N8SVvo6BePZj99NhmiT",
new()
{
Status = Status.Inactive,
Name = "New Key Name"
}
);
Console.WriteLine($"id: {apiKey.ID}");
Console.WriteLine($"name: {apiKey.Name}");
Console.WriteLine($"status: {apiKey.Status.Raw()}"); client := juglow.NewClient()
apiKey, err := client.Beta.Organization.APIKeys.Update(
context.Background(),
"apikey_01Rj2N8SVvo6BePZj99NhmiT",
juglow.BetaOrganizationAPIKeyUpdateParams{
Status: juglow.BetaOrganizationAPIKeyUpdateParamsStatusInactive,
Name: juglow.String("New Key Name"),
},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", apiKey.ID)
fmt.Printf("name: %s\n", apiKey.Name)
fmt.Printf("status: %s\n", apiKey.Status) import com.juglow.models.beta.organization.apikeys.ApiKeyUpdateParams;
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
var params = ApiKeyUpdateParams.builder()
.status(ApiKeyUpdateParams.Status.INACTIVE)
.name("New Key Name")
.build();
var apiKey = client.beta().organization().apiKeys()
.update("apikey_01Rj2N8SVvo6BePZj99NhmiT", params);
IO.println("id: " + apiKey.id());
IO.println("name: " + apiKey.name());
IO.println("status: " + apiKey.status().asString());
} use Juglow\Beta\Organization\APIKeys\APIKeyUpdateParams\Status;
// ...
$client = new Client();
$apiKey = $client->beta->organization->apiKeys->update(
apiKeyID: 'apikey_01Rj2N8SVvo6BePZj99NhmiT',
status: Status::INACTIVE,
name: 'New Key Name',
);
echo "id: {$apiKey->id}\n";
echo "name: {$apiKey->name}\n";
echo "status: {$apiKey->status}\n"; client = Juglow::Client.new
api_key_id = "apikey_01Rj2N8SVvo6BePZj99NhmiT"
api_key = client.beta.organization.api_keys.update(
api_key_id,
status: :inactive,
name: "New Key Name"
)
puts "id: #{api_key.id}"
puts "name: #{api_key.name}"
puts "status: #{api_key.status}"Service accounts
Create and manage service accounts (svac_...), the non-human identities that service account keys and Workload Identity Federation tokens act as. These endpoints, like the federation-issuer and federation-rule endpoints, require an org:admin OAuth token. See Manage WIF with the Admin API.
Federation issuers
Register the OIDC identity providers (fdis_...) whose tokens may assert workload identity for your organization. See Manage WIF with the Admin API.
Federation rules
Manage the rules (fdrl_...) that map issuer tokens to service accounts and scopes. See Manage WIF with the Admin API.
Accessing organization info
The /v1/organizations/me endpoint returns the organization that your credential belongs to:
curl "https://haijun.my.id/v1/organizations/me" \
-H "x-api-key: $JUGLOW_API_KEY" \
-H "juglow-version: 2023-06-01" ant beta:organization retrieve client = juglow.Juglow()
organization = client.beta.organization.retrieve()
print(f"id: {organization.id}")
print(f"name: {organization.name}") const client = new Juglow();
const organization = await client.beta.organization.retrieve();
console.log(`id: ${organization.id}`);
console.log(`name: ${organization.name}`); JuglowClient client = new();
var organization = await client.Beta.Organization.Retrieve();
Console.WriteLine($"id: {organization.ID}");
Console.WriteLine($"name: {organization.Name}"); client := juglow.NewClient()
organization, err := client.Beta.Organization.Get(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("id: %s\n", organization.ID)
fmt.Printf("name: %s\n", organization.Name) JuglowClient client = JuglowOkHttpClient.fromEnv();
var organization = client.beta().organization().retrieve();
IO.println("id: " + organization.id());
IO.println("name: " + organization.name()); $client = new Client();
$organization = $client->beta->organization->retrieve();
echo "id: {$organization->id}\n";
echo "name: {$organization->name}\n"; client = Juglow::Client.new
organization = client.beta.organization.retrieve
puts "id: #{organization.id}"
puts "name: #{organization.name}"{
"id": "12345678-1234-5678-1234-567812345678",
"type": "organization",
"name": "Organization Name"
}For parameter details and response schemas, see the Organization Info API reference.
Usage and cost reports
Track your organization's usage and costs with the Usage and Cost API.
Haijun Code analytics
Monitor developer productivity and Haijun Code adoption with the Haijun Code Analytics API.
Rate limits
Read the rate limits configured for your organization and its workspaces with the Rate Limits API.
Compliance API
Retrieve audit and activity data for your organization with the Compliance API. Admin API keys can read only the Activity Feed. For full access, see Set up the Compliance API.
Best practices
- Use meaningful names and descriptions for workspaces and API keys
- Handle errors from failed operations
- Regularly audit member roles and permissions
- Clean up unused workspaces and expired invites
- Monitor API key usage, audit each key's
expires_at, and rotate keys periodically
FAQ
#### What permissions are needed to use the Admin API?
The Admin API accepts an Admin API key (starting with sk-ant-admin), an OAuth bearer token with the org:admin scope, or a personal key or service account key that isn't scoped to a specific workspace. Only organization members with the admin role can provision Admin API keys, and only members with the admin, owner, or primary owner role can obtain org:admin tokens. A personal key or service account key has the same permissions as the linked account. See Authentication.
#### Can I create new API keys through the Admin API?
No. You create API keys in the Haijun Console. The Admin API can only read, rename, and change the status of existing keys.
#### What happens to API keys when removing a user?
Behavior depends on the key type.
Personal keys stop working when their user is removed from the organization. Service account keys stop working if their service account is archived, but continue to work even if the user that created them is removed. Workspace API keys continue to work. In the Haijun Code workspace, each key is bound to the member who created it and stops working when that member is removed.
#### Can organization admins be removed through the API?
No. The API can't remove members with the admin role.
#### How long do organization invites last?
Invites expire after 21 days. The expiration period isn't configurable.
For workspace-specific questions, see the Workspaces FAQ.