Lararouter
API reference

Models

GET /v1/models and GET /v1/models/{model}. What's available, what it costs, and what it can do.

Model availability is per region, so ask the host you're actually calling rather than assuming a global catalogue.

List models

GET /v1/models?capability=chat HTTP/1.1
Host: REGION.api.lararouter.com
Authorization: Bearer $LARAROUTER_API_KEY

Requires the models:read scope.

curl -G https://REGION.api.lararouter.com/v1/models \
  -H "Authorization: Bearer $LARAROUTER_API_KEY" \
  -d "capability=chat"

Prop

Type

{
  "object": "list",
  "data": [
    {
      "id": "llama-3.3-70b",
      "object": "model",
      "created": 1733011200,
      "owned_by": "meta",
      "capability": "chat",
      "description": "A strong general-purpose model for summarization and reasoning.",
      "context_window": 128000,
      "max_output_tokens": 8192,
      "supports": {
        "tools": true,
        "structured_output": true,
        "vision": false
      },
      "pricing": {
        "batch": { "input_per_1m": 0.30, "output_per_1m": 0.40 }
      },
      "regions": ["us", "eu", "in"]
    }
  ],
  "has_more": true,
  "next_cursor": "llama-3.3-70b"
}

Retrieve a model

GET /v1/models/llama-3.3-70b HTTP/1.1
Host: REGION.api.lararouter.com
Authorization: Bearer $LARAROUTER_API_KEY
curl https://REGION.api.lararouter.com/v1/models/llama-3.3-70b \
  -H "Authorization: Bearer $LARAROUTER_API_KEY"

Fields

Prop

Type

Not available here

Requesting a model your region doesn't carry returns 404, and the error names the regions that do:

{
  "error": {
    "type": "invalid_request_error",
    "code": "model_not_available_in_region",
    "message": "Model 'command-r-35b' is not available in region 'in'.",
    "available_in": ["us", "eu"]
  }
}

Picking a model at runtime

Because pricing and capabilities are on the model object, you can choose while building the batch rather than hardcoding. This picks the cheapest model that can enforce a schema:

namespace App\Actions\Lararouter;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;

class ResolveModel
{
    public function handle(bool $needsSchema = false): string
    {
        $models = Cache::remember('lararouter.models', now()->addHour(), fn () =>
            Http::withToken(config('services.lararouter.key'))
                ->get('https://REGION.api.lararouter.com/v1/models', ['capability' => 'chat'])
                ->throw()
                ->json('data')
        );

        return collect($models)
            ->when($needsSchema, fn ($models) => $models->where('supports.structured_output', true))
            ->sortBy('pricing.batch.input_per_1m')
            ->value('id') ?? 'llama-3.3-70b';
    }
}

Cache the list. It changes when models are added or retired, not per batch, and an hour is a reasonable window.

Cheapest is not always cheapest

Input rate is only half the picture. A small model that needs a second batch to produce valid JSON costs more than a larger one that gets it right first time, and costs you another completion window. Group usage by model and compare real spend rather than reasoning from the rate card.

On this page