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_KEYRequires 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_KEYcurl 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.