> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.lettbestilt.no/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.lettbestilt.no/_mcp/server.

# Get the preparation time

GET https://www.lettbestilt.no/api/v1/prep-time

Returns the current preparation time: base time plus rush, already added up. This is the number to show as "ready in about X min" on the menu and in checkout, and exactly what `POST /orders` uses to set `estimatedReadyAt` on an as-soon-as-possible order.

It is a separate endpoint because `/restaurant` and `/menu` are cached at the edge for up to 5–11 minutes, and rush is exactly when that delay hurts. This response is never cached (`no-store`). Cache it yourself for 20–30 seconds, and fetch it again when checkout opens.

Same authentication as the rest of the API (API key or trusted browser origin), so you can call it from the browser on a verified domain. Rate limit: 600 requests per 60 seconds per slug and IP.

Reference: https://docs.lettbestilt.no/api-reference/restaurant-and-menu/get-prep-time

## Authentication

- `Authorization` header (bearer token, required) — Either this or a trusted browser origin. The restaurant's API key, sent as `Authorization: Bearer lbs_…`. Use it from your server only, never in browser code. Keys are issued per restaurant by LettBestilt.
- `Origin` header (required) — Either this or an API key. No key is needed when the request's `Origin` header is trusted for this restaurant: `https://{slug}.lettbestilt.no`, a verified domain of the restaurant, or a partner origin LettBestilt has bound to the restaurant. Browsers set `Origin` themselves; it is not something you configure. Not accepted by `GET /site-gate`, which requires an API key.

## Request

### Query parameters

- `slug` (string, required) — The restaurant's slug.

## Response

### 200

The current preparation time.

- `prepTime` (PrepTime, required) — The current preparation time, already added up: base time plus rush. Show `pickupMinutes` or `deliveryMinutes` as "about X min". They are exactly what `POST /orders` uses to set `estimatedReadyAt` (now plus the minutes) on an as-soon-as-possible order. `rushDelayMinutes` above 0 means the kitchen has turned on rush, which turns itself off at the next midnight (Oslo time). Do not calculate anything yourself; show the numbers as they are.

## Errors

### 400 Bad Request Error

`MISSING_SLUG`: the `slug` query parameter is missing.

- `error` (ErrorBody, required)

### 401 Unauthorized Error

`UNAUTHORIZED`: missing or invalid API key, and the request does not come from a trusted browser origin.

- `error` (ErrorBody, required)

### 404 Not Found Error

`RESTAURANT_NOT_FOUND`: no live restaurant has this slug.

- `error` (ErrorBody, required)

### 429 Too Many Requests Error

`RATE_LIMITED`: more than 600 requests in 60 seconds for this slug and IP.

- `error` (ErrorBody, required)

## Types

### PrepTime

The current preparation time, already added up: base time plus rush. Show `pickupMinutes` or `deliveryMinutes` as "about X min". They are exactly what `POST /orders` uses to set `estimatedReadyAt` (now plus the minutes) on an as-soon-as-possible order. `rushDelayMinutes` above 0 means the kitchen has turned on rush, which turns itself off at the next midnight (Oslo time). Do not calculate anything yourself; show the numbers as they are.

- `pickupMinutes` (integer, required) — Base pickup time plus rush.
- `deliveryMinutes` (integer, required) — Base delivery time plus rush.
- `rushDelayMinutes` (integer, required) — Extra minutes from rush right now (0 = no rush).
- `basePickupMinutes` (integer, required) — The restaurant's normal pickup time (same as `defaultPrepMinutes`).
- `baseDeliveryMinutes` (integer, required) — The restaurant's normal delivery time (same as `defaultDeliveryMinutes`).

### ErrorBody

- `code` (enum, required) — A machine-readable error code.
  - Allowed values: `MISSING_SLUG`, `MISSING_TOKEN`, `INVALID_JSON`, `INVALID_SUCCESS_URL`, `INVALID_CANCEL_URL`, `VALIDATION_FAILED`, `RESTAURANT_NOT_FOUND`, `ORDER_NOT_FOUND`, `RATE_LIMITED`, `BAD_REQUEST`, `UNAUTHORIZED`, `FORBIDDEN`, `POPUP_NOT_AVAILABLE`, `PRICE_CHANGED`, `PAYMENT_INCOMPLETE`, `PAYMENT_PENDING`, `PAYMENT_PROVIDER_INVALID`, `FULFILLMENT_NOT_ALLOWED`, `IDEMPOTENCY_CONFLICT`, `DINE_IN_DISABLED`, `PARTY_TOO_LARGE`, `TOO_EARLY`, `INTERNAL_ERROR`
- `message` (string, required) — A human-readable explanation. Often in Norwegian, and for business rules usually suitable to show the customer.
- `details` (any, optional) — Extra data for some codes, for example `issues` for `VALIDATION_FAILED` or the totals for `PRICE_CHANGED`.

## Examples

**Response**

```json
{
  "prepTime": {
    "pickupMinutes": 35,
    "deliveryMinutes": 60,
    "rushDelayMinutes": 15,
    "basePickupMinutes": 20,
    "baseDeliveryMinutes": 45
  }
}
```

**SDK Code**

```python Restaurant and menu_getPrepTime_example
import requests

url = "https://www.lettbestilt.no/api/v1/prep-time"

querystring = {"slug":"slug"}

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript Restaurant and menu_getPrepTime_example
const url = 'https://www.lettbestilt.no/api/v1/prep-time?slug=slug';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Restaurant and menu_getPrepTime_example
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://www.lettbestilt.no/api/v1/prep-time?slug=slug"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Restaurant and menu_getPrepTime_example
require 'uri'
require 'net/http'

url = URI("https://www.lettbestilt.no/api/v1/prep-time?slug=slug")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java Restaurant and menu_getPrepTime_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://www.lettbestilt.no/api/v1/prep-time?slug=slug")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php Restaurant and menu_getPrepTime_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://www.lettbestilt.no/api/v1/prep-time?slug=slug', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp Restaurant and menu_getPrepTime_example
using RestSharp;

var client = new RestClient("https://www.lettbestilt.no/api/v1/prep-time?slug=slug");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift Restaurant and menu_getPrepTime_example
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://www.lettbestilt.no/api/v1/prep-time?slug=slug")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```