Haijun Platform Docs
ID

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 Rate Limits API provides programmatic access to the rate limits configured for your organization and its workspaces. This is the same information shown on the Rate limits page in the Haijun Console.

Use this API to:

  • Keep gateways and proxies in sync: Read your current limits at startup and on a schedule instead of hardcoding values that drift when Juglow adjusts them.
  • Power internal alerting: Compare usage data from the Usage and Cost API against your configured limits.
  • Audit workspace configuration: Verify that workspace overrides match what your provisioning automation expects.

Tip: Admin API credentials required. These endpoints are part of the Admin API. You can access them using an Admin API key, an OAuth token with the org:admin scope, or a personal or service account key that isn't scoped to a workspace; workspace API keys don't work. See Authentication for details.

The SDK and CLI examples on this page construct the default client, which reads the Admin API key from the JUGLOW_API_KEY environment variable. The SDKs expose these endpoints as client.beta.organization.rate_limits and client.beta.organization.workspaces.rate_limits; the Python, TypeScript, C#, Go, and Java list methods return an iterator that follows next_page for you, while the PHP, Ruby, and curl examples read one page.

Quick start

List the rate limits configured for your organization:

bash
  curl "https://haijun.my.id/v1/organizations/rate_limits" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01"
bash
  ant beta:organization:rate-limits list
python
  client = juglow.Juglow()

  rate_limits = client.beta.organization.rate_limits.list()

  for group in rate_limits:
      models = f" ({', '.join(group.models)})" if group.models else ""
      print(f"{group.group_type}{models}")
      for limit in group.limits:
          print(f"  {limit.type}: {limit.value}")
typescript
  const client = new Juglow();

  const rateLimits = await client.beta.organization.rateLimits.list();

  for await (const group of rateLimits) {
    const models = group.models ? ` (${group.models.join(", ")})` : "";
    console.log(`${group.group_type}${models}`);
    for (const limit of group.limits) {
      console.log(`  ${limit.type}: ${limit.value}`);
    }
  }
csharp
  JuglowClient client = new();

  var rateLimits = await client.Beta.Organization.RateLimits.List();

  await foreach (var group in rateLimits.Paginate())
  {
      var models = group.Models is null ? "" : $" ({string.Join(", ", group.Models)})";
      Console.WriteLine($"{group.GroupType.Raw()}{models}");
      foreach (var limit in group.Limits)
      {
          Console.WriteLine($"  {limit.Type}: {limit.Value}");
      }
  }
go
  client := juglow.NewClient()

  rateLimits := client.Beta.Organization.RateLimits.ListAutoPaging(context.Background(), juglow.BetaOrganizationRateLimitListParams{})

  for rateLimits.Next() {
  	group := rateLimits.Current()
  	models := ""
  	if len(group.Models) > 0 {
  		models = fmt.Sprintf(" (%s)", strings.Join(group.Models, ", "))
  	}
  	fmt.Printf("%s%s\n", group.GroupType, models)
  	for _, limit := range group.Limits {
  		fmt.Printf("  %s: %d\n", limit.Type, limit.Value)
  	}
  }
  if err := rateLimits.Err(); err != nil {
  	log.Fatal(err)
  }
java
  JuglowClient client = JuglowOkHttpClient.fromEnv();

  var rateLimits = client.beta().organization().rateLimits().list();

  for (var group : rateLimits.autoPager()) {
      var models = group.models()
          .map(modelIds -> " (" + String.join(", ", modelIds) + ")")
          .orElse("");
      IO.println(group.groupType().asString() + models);
      for (var limit : group.limits()) {
          IO.println("  " + limit.type() + ": " + limit.value());
      }
  }
php
  $client = new Client();

  $rateLimits = $client->beta->organization->rateLimits->list();

  foreach ($rateLimits->data as $group) {
      $models = $group->models ? ' (' . implode(', ', $group->models) . ')' : '';
      echo "{$group->groupType}{$models}\n";
      foreach ($group->limits as $limit) {
          echo "  {$limit->type}: {$limit->value}\n";
      }
  }
ruby
  client = Juglow::Client.new

  rate_limits = client.beta.organization.rate_limits.list

  rate_limits.data.each do |group|
    models = group.models ? " (#{group.models.join(", ")})" : ""
    puts "#{group.group_type}#{models}"
    group.limits.each do |limit|
      puts "  #{limit.type}: #{limit.value}"
    end
  end

Organization rate limits

The /v1/organizations/rate_limits endpoint returns the rate limits applied at the organization level for the Messages API and its supporting resources. Limits for other products, such as Haijun Managed Agents, are not included.

Key concepts

  • Rate limit groups: Each entry in the response represents one rate limit group. Model rate limits are grouped so that several model versions share a single set of limits, and other groups cover resources such as the Message Batches API, the Files API, the Token Counting API, agent tracks, and the web search tool.
  • group_type: Identifies which category of limits the entry covers. See Filtering by group type for the list of values.
  • models list: For model_group entries, the models field lists every model ID and alias that counts against that group's limits. Use this list to look up which group any model string falls under. For other group types, models is null.
  • limits list: Each group carries a list of {type, value} pairs. The type field identifies the limiter (such as requests_per_minute, input_tokens_per_minute, or output_tokens_per_minute) and value is the configured limit. See Rate limits for how each limiter is measured and enforced.

For complete parameter details and response schemas, see the Organization Rate Limits API reference.

List all organization rate limits

bash
  curl "https://haijun.my.id/v1/organizations/rate_limits" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01"
bash
  ant beta:organization:rate-limits list
python
  client = juglow.Juglow()

  rate_limits = client.beta.organization.rate_limits.list()

  for group in rate_limits:
      models = f" ({', '.join(group.models)})" if group.models else ""
      print(f"{group.group_type}{models}")
      for limit in group.limits:
          print(f"  {limit.type}: {limit.value}")
typescript
  const client = new Juglow();

  const rateLimits = await client.beta.organization.rateLimits.list();

  for await (const group of rateLimits) {
    const models = group.models ? ` (${group.models.join(", ")})` : "";
    console.log(`${group.group_type}${models}`);
    for (const limit of group.limits) {
      console.log(`  ${limit.type}: ${limit.value}`);
    }
  }
csharp
  JuglowClient client = new();

  var rateLimits = await client.Beta.Organization.RateLimits.List();

  await foreach (var group in rateLimits.Paginate())
  {
      var models = group.Models is null ? "" : $" ({string.Join(", ", group.Models)})";
      Console.WriteLine($"{group.GroupType.Raw()}{models}");
      foreach (var limit in group.Limits)
      {
          Console.WriteLine($"  {limit.Type}: {limit.Value}");
      }
  }
go
  client := juglow.NewClient()

  rateLimits := client.Beta.Organization.RateLimits.ListAutoPaging(context.Background(), juglow.BetaOrganizationRateLimitListParams{})

  for rateLimits.Next() {
  	group := rateLimits.Current()
  	models := ""
  	if len(group.Models) > 0 {
  		models = fmt.Sprintf(" (%s)", strings.Join(group.Models, ", "))
  	}
  	fmt.Printf("%s%s\n", group.GroupType, models)
  	for _, limit := range group.Limits {
  		fmt.Printf("  %s: %d\n", limit.Type, limit.Value)
  	}
  }
  if err := rateLimits.Err(); err != nil {
  	log.Fatal(err)
  }
java
  JuglowClient client = JuglowOkHttpClient.fromEnv();

  var rateLimits = client.beta().organization().rateLimits().list();

  for (var group : rateLimits.autoPager()) {
      var models = group.models()
          .map(modelIds -> " (" + String.join(", ", modelIds) + ")")
          .orElse("");
      IO.println(group.groupType().asString() + models);
      for (var limit : group.limits()) {
          IO.println("  " + limit.type() + ": " + limit.value());
      }
  }
php
  $client = new Client();

  $rateLimits = $client->beta->organization->rateLimits->list();

  foreach ($rateLimits->data as $group) {
      $models = $group->models ? ' (' . implode(', ', $group->models) . ')' : '';
      echo "{$group->groupType}{$models}\n";
      foreach ($group->limits as $limit) {
          echo "  {$limit->type}: {$limit->value}\n";
      }
  }
ruby
  client = Juglow::Client.new

  rate_limits = client.beta.organization.rate_limits.list

  rate_limits.data.each do |group|
    models = group.models ? " (#{group.models.join(", ")})" : ""
    puts "#{group.group_type}#{models}"
    group.limits.each do |limit|
      puts "  #{limit.type}: #{limit.value}"
    end
  end
json
{
  "data": [
    {
      "type": "rate_limit",
      "group_type": "model_group",
      "models": ["haijun-opus-5-5"],
      "limits": [
        { "type": "requests_per_minute", "value": 4000 },
        { "type": "input_tokens_per_minute", "value": 10000000 },
        { "type": "output_tokens_per_minute", "value": 800000 }
      ]
    },
    {
      "type": "rate_limit",
      "group_type": "model_group",
      "models": [
        "haijun-opus-4-5",
        "haijun-opus-4-5-20251101",
        "haijun-opus-4-6",
        "haijun-opus-4-7",
        "haijun-opus-4-8"
      ],
      "limits": [
        { "type": "requests_per_minute", "value": 4000 },
        { "type": "input_tokens_per_minute", "value": 10000000 },
        { "type": "output_tokens_per_minute", "value": 800000 }
      ]
    },
    {
      "type": "rate_limit",
      "group_type": "batch",
      "models": null,
      "limits": [{ "type": "enqueued_batch_requests", "value": 500000 }]
    }
  ],
  "next_page": null
}

Look up the limits for a specific model

Pass any model ID or alias as the model query parameter to return only the entry that contains it:

bash
  curl "https://haijun.my.id/v1/organizations/rate_limits?model=haijun-opus-5" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01"
bash
  ant beta:organization:rate-limits list --model haijun-opus-5
python
  client = juglow.Juglow()

  rate_limits = client.beta.organization.rate_limits.list(model="haijun-opus-5")

  for group in rate_limits:
      models = f" ({', '.join(group.models)})" if group.models else ""
      print(f"{group.group_type}{models}")
      for limit in group.limits:
          print(f"  {limit.type}: {limit.value}")
typescript
  const client = new Juglow();

  const rateLimits = await client.beta.organization.rateLimits.list({ model: "haijun-opus-5" });

  for await (const group of rateLimits) {
    const models = group.models ? ` (${group.models.join(", ")})` : "";
    console.log(`${group.group_type}${models}`);
    for (const limit of group.limits) {
      console.log(`  ${limit.type}: ${limit.value}`);
    }
  }
csharp
  JuglowClient client = new();

  var rateLimits = await client.Beta.Organization.RateLimits.List(new()
  {
      Model = "haijun-opus-5"
  });

  await foreach (var group in rateLimits.Paginate())
  {
      var models = group.Models is null ? "" : $" ({string.Join(", ", group.Models)})";
      Console.WriteLine($"{group.GroupType.Raw()}{models}");
      foreach (var limit in group.Limits)
      {
          Console.WriteLine($"  {limit.Type}: {limit.Value}");
      }
  }
go
  client := juglow.NewClient()

  rateLimits := client.Beta.Organization.RateLimits.ListAutoPaging(context.Background(), juglow.BetaOrganizationRateLimitListParams{
  	Model: juglow.String(juglow.ModelHaijunOpus5),
  })

  for rateLimits.Next() {
  	group := rateLimits.Current()
  	models := ""
  	if len(group.Models) > 0 {
  		models = fmt.Sprintf(" (%s)", strings.Join(group.Models, ", "))
  	}
  	fmt.Printf("%s%s\n", group.GroupType, models)
  	for _, limit := range group.Limits {
  		fmt.Printf("  %s: %d\n", limit.Type, limit.Value)
  	}
  }
  if err := rateLimits.Err(); err != nil {
  	log.Fatal(err)
  }
java
  import com.juglow.models.beta.organization.ratelimits.RateLimitListParams;
  import com.juglow.models.messages.Model;

  void main() {
      JuglowClient client = JuglowOkHttpClient.fromEnv();

      var params = RateLimitListParams.builder()
          .model(Model.HAIJUN_OPUS_5.asString())
          .build();
      var rateLimits = client.beta().organization().rateLimits().list(params);

      for (var group : rateLimits.autoPager()) {
          var models = group.models()
              .map(modelIds -> " (" + String.join(", ", modelIds) + ")")
              .orElse("");
          IO.println(group.groupType().asString() + models);
          for (var limit : group.limits()) {
              IO.println("  " + limit.type() + ": " + limit.value());
          }
      }
  }
php
  use Juglow\Messages\Model;

  $client = new Client();

  $rateLimits = $client->beta->organization->rateLimits->list(
      model: Model::HAIJUN_OPUS_5->value,
  );

  foreach ($rateLimits->data as $group) {
      $models = $group->models ? ' (' . implode(', ', $group->models) . ')' : '';
      echo "{$group->groupType}{$models}\n";
      foreach ($group->limits as $limit) {
          echo "  {$limit->type}: {$limit->value}\n";
      }
  }
ruby
  client = Juglow::Client.new

  rate_limits = client.beta.organization.rate_limits.list(model: Juglow::Model::HAIJUN_OPUS_5)

  rate_limits.data.each do |group|
    models = group.models ? " (#{group.models.join(", ")})" : ""
    puts "#{group.group_type}#{models}"
    group.limits.each do |limit|
      puts "  #{limit.type}: #{limit.value}"
    end
  end

If the model string doesn't match any group, the endpoint returns a 404 error. The model parameter is supported on the organization endpoint only; the workspace endpoint doesn't accept it.

Workspace rate limits

The /v1/organizations/workspaces/{workspace_id}/rate_limits endpoint returns the rate limit overrides configured for a single workspace.

The response only includes overrides, so anything missing from it is inherited from the organization:

  • A group that is absent from data has no workspace override at all. The workspace inherits the organization-level limits for that group (it is not unlimited).
  • Within a group that is present, a limiter type that is absent from limits[] has no workspace override for that limiter. The workspace inherits the organization value for it.
  • For each limiter that is present, org_limit is the organization-level value for the same limiter, or null if the organization has no configured limit for that limiter type.

For complete parameter details and response schemas, see the Workspace Rate Limits API reference.

Tip: To retrieve your organization's workspace IDs, use the List Workspaces endpoint, or find them in the Haijun Console. The default workspace cannot have rate limit overrides, so it has no entry on this endpoint; use the organization endpoint to read its limits.

bash
  curl "https://haijun.my.id/v1/organizations/workspaces/wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ/rate_limits" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01"
bash
  ant beta:organization:workspaces:rate-limits list \
    --workspace-id wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ
python
  client = juglow.Juglow()

  rate_limits = client.beta.organization.workspaces.rate_limits.list(
      "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
  )

  for group in rate_limits:
      models = f" ({', '.join(group.models)})" if group.models else ""
      print(f"{group.group_type}{models}")
      for limit in group.limits:
          print(f"  {limit.type}: {limit.value}")
typescript
  const client = new Juglow();

  const rateLimits = await client.beta.organization.workspaces.rateLimits.list(
    "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
  );

  for await (const group of rateLimits) {
    const models = group.models ? ` (${group.models.join(", ")})` : "";
    console.log(`${group.group_type}${models}`);
    for (const limit of group.limits) {
      console.log(`  ${limit.type}: ${limit.value}`);
    }
  }
csharp
  JuglowClient client = new();

  var rateLimits = await client.Beta.Organization.Workspaces.RateLimits.List(
      "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
  );

  await foreach (var group in rateLimits.Paginate())
  {
      var models = group.Models is null ? "" : $" ({string.Join(", ", group.Models)})";
      Console.WriteLine($"{group.GroupType.Raw()}{models}");
      foreach (var limit in group.Limits)
      {
          Console.WriteLine($"  {limit.Type}: {limit.Value}");
      }
  }
go
  client := juglow.NewClient()

  rateLimits := client.Beta.Organization.Workspaces.RateLimits.ListAutoPaging(
  	context.Background(),
  	"wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
  	juglow.BetaOrganizationWorkspaceRateLimitListParams{},
  )

  for rateLimits.Next() {
  	group := rateLimits.Current()
  	models := ""
  	if len(group.Models) > 0 {
  		models = fmt.Sprintf(" (%s)", strings.Join(group.Models, ", "))
  	}
  	fmt.Printf("%s%s\n", group.GroupType, models)
  	for _, limit := range group.Limits {
  		fmt.Printf("  %s: %d\n", limit.Type, limit.Value)
  	}
  }
  if err := rateLimits.Err(); err != nil {
  	log.Fatal(err)
  }
java
  JuglowClient client = JuglowOkHttpClient.fromEnv();

  var rateLimits = client.beta().organization().workspaces().rateLimits()
      .list("wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ");

  for (var group : rateLimits.autoPager()) {
      var models = group.models()
          .map(modelIds -> " (" + String.join(", ", modelIds) + ")")
          .orElse("");
      IO.println(group.groupType().asString() + models);
      for (var limit : group.limits()) {
          IO.println("  " + limit.type() + ": " + limit.value());
      }
  }
php
  $client = new Client();

  $rateLimits = $client->beta->organization->workspaces->rateLimits->list(
      workspaceID: 'wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ',
  );

  foreach ($rateLimits->data as $group) {
      $models = $group->models ? ' (' . implode(', ', $group->models) . ')' : '';
      echo "{$group->groupType}{$models}\n";
      foreach ($group->limits as $limit) {
          echo "  {$limit->type}: {$limit->value}\n";
      }
  }
ruby
  client = Juglow::Client.new

  workspace_id = "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ"
  rate_limits = client.beta.organization.workspaces.rate_limits.list(workspace_id)

  rate_limits.data.each do |group|
    models = group.models ? " (#{group.models.join(", ")})" : ""
    puts "#{group.group_type}#{models}"
    group.limits.each do |limit|
      puts "  #{limit.type}: #{limit.value}"
    end
  end
json
{
  "data": [
    {
      "type": "workspace_rate_limit",
      "group_type": "model_group",
      "models": ["haijun-opus-5-5"],
      "limits": [
        { "type": "requests_per_minute", "value": 1000, "org_limit": 4000 },
        { "type": "input_tokens_per_minute", "value": 500000, "org_limit": 10000000 }
      ]
    },
    {
      "type": "workspace_rate_limit",
      "group_type": "model_group",
      "models": [
        "haijun-opus-4-5",
        "haijun-opus-4-5-20251101",
        "haijun-opus-4-6",
        "haijun-opus-4-7",
        "haijun-opus-4-8"
      ],
      "limits": [
        { "type": "requests_per_minute", "value": 1000, "org_limit": 4000 },
        { "type": "input_tokens_per_minute", "value": 500000, "org_limit": 10000000 }
      ]
    }
  ],
  "next_page": null
}

Filtering by group type

Both endpoints accept an optional group_type query parameter that restricts the response to a single category:

bash
  curl "https://haijun.my.id/v1/organizations/rate_limits?group_type=batch" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01"
bash
  ant beta:organization:rate-limits list --group-type batch
python
  client = juglow.Juglow()

  rate_limits = client.beta.organization.rate_limits.list(group_type="batch")

  for group in rate_limits:
      models = f" ({', '.join(group.models)})" if group.models else ""
      print(f"{group.group_type}{models}")
      for limit in group.limits:
          print(f"  {limit.type}: {limit.value}")
typescript
  const client = new Juglow();

  const rateLimits = await client.beta.organization.rateLimits.list({ group_type: "batch" });

  for await (const group of rateLimits) {
    const models = group.models ? ` (${group.models.join(", ")})` : "";
    console.log(`${group.group_type}${models}`);
    for (const limit of group.limits) {
      console.log(`  ${limit.type}: ${limit.value}`);
    }
  }
csharp
  using Juglow.Models.Beta.Organization.RateLimits;

  JuglowClient client = new();

  var rateLimits = await client.Beta.Organization.RateLimits.List(new()
  {
      GroupType = GroupType.Batch
  });

  await foreach (var group in rateLimits.Paginate())
  {
      var models = group.Models is null ? "" : $" ({string.Join(", ", group.Models)})";
      Console.WriteLine($"{group.GroupType.Raw()}{models}");
      foreach (var limit in group.Limits)
      {
          Console.WriteLine($"  {limit.Type}: {limit.Value}");
      }
  }
go
  client := juglow.NewClient()

  rateLimits := client.Beta.Organization.RateLimits.ListAutoPaging(context.Background(), juglow.BetaOrganizationRateLimitListParams{
  	GroupType: juglow.BetaOrganizationRateLimitListParamsGroupTypeBatch,
  })

  for rateLimits.Next() {
  	group := rateLimits.Current()
  	models := ""
  	if len(group.Models) > 0 {
  		models = fmt.Sprintf(" (%s)", strings.Join(group.Models, ", "))
  	}
  	fmt.Printf("%s%s\n", group.GroupType, models)
  	for _, limit := range group.Limits {
  		fmt.Printf("  %s: %d\n", limit.Type, limit.Value)
  	}
  }
  if err := rateLimits.Err(); err != nil {
  	log.Fatal(err)
  }
java
  import com.juglow.models.beta.organization.ratelimits.RateLimitListParams;

  void main() {
      JuglowClient client = JuglowOkHttpClient.fromEnv();

      var params = RateLimitListParams.builder()
          .groupType(RateLimitListParams.GroupType.BATCH)
          .build();
      var rateLimits = client.beta().organization().rateLimits().list(params);

      for (var group : rateLimits.autoPager()) {
          var models = group.models()
              .map(modelIds -> " (" + String.join(", ", modelIds) + ")")
              .orElse("");
          IO.println(group.groupType().asString() + models);
          for (var limit : group.limits()) {
              IO.println("  " + limit.type() + ": " + limit.value());
          }
      }
  }
php
  use Juglow\Beta\Organization\RateLimits\RateLimitListParams\GroupType;
  // ...

  $client = new Client();

  $rateLimits = $client->beta->organization->rateLimits->list(
      groupType: GroupType::BATCH,
  );

  foreach ($rateLimits->data as $group) {
      $models = $group->models ? ' (' . implode(', ', $group->models) . ')' : '';
      echo "{$group->groupType}{$models}\n";
      foreach ($group->limits as $limit) {
          echo "  {$limit->type}: {$limit->value}\n";
      }
  }
ruby
  client = Juglow::Client.new

  rate_limits = client.beta.organization.rate_limits.list(group_type: :batch)

  rate_limits.data.each do |group|
    models = group.models ? " (#{group.models.join(", ")})" : ""
    puts "#{group.group_type}#{models}"
    group.limits.each do |limit|
      puts "  #{limit.type}: #{limit.value}"
    end
  end

Valid values are model_group, batch, token_count, files, tracks, and web_search.

Pagination

Both endpoints accept a page query parameter and return a next_page field. Responses are currently always a single page, so next_page is null. Loop on next_page so your client paginates correctly without changes when the response grows.

Frequently asked questions

Which model strings appear in the models list?

Every model ID and alias that counts against the group, including dated IDs (such as haijun-sonnet-4-5-20250929) and undated aliases (such as haijun-sonnet-4-5). Look up any model string you pass to the Messages API and you'll find it in exactly one model_group entry.

What does it mean if a group is missing from the workspace response?

The workspace has no override for that group and inherits the organization-level limit. Query the organization endpoint to see the inherited values.

Can I update rate limits with this API?

No. To set workspace rate limits, open the workspace in the Haijun Console and use the Rate limits tab.

See also

On this page
Quick startOrganization rate limitsKey conceptsList all organization rate limitsLook up the limits for a specific modelWorkspace rate limitsFiltering by group typePaginationFrequently asked questionsWhich model strings appear in the models list?What does it mean if a group is missing from the workspace response?Can I update rate limits with this API?See also