---
title: REST API Recipes
url: https://docs.kaltura.com/docs/getting-started/authentication/ks-api-recipes
---

## REST API Recipes

All calls use the v3 endpoint with form-encoded POST data and `format=1` for JSON responses.

`Base URL: https://www.kaltura.com/api_v3/` (this URL can change depending on geo region, or deployment, the account was configured on)

### Generate a KS (backend) with session.start

```bash
curl -X POST "$KALTURA_SERVICE_URL/service/session/action/start" \
  -d "partnerId=$KALTURA_PARTNER_ID" \
  -d "secret=$KALTURA_ADMIN_SECRET" \
  -d "userId=testUser" \
  -d "type=0" \
  -d "expiry=1800" \
  -d "privileges=sview:*" \
  -d "format=1"
```

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `secret` | string | Yes | Admin secret (`type=2`) or user secret (`type=0`) |
| `partnerId` | integer | Yes | Your Kaltura partner ID |
| `type` | integer | Yes | `0` = USER, `2` = ADMIN |
| `userId` | string | No | User ID for the session (default: empty) |
| `expiry` | integer | No | TTL in seconds (default: 86400 = 24 hours) |
| `privileges` | string | No | Comma-separated privilege strings (e.g., `sview:*,edit:*`) |

**Response:** The KS string (with `format=1`, wrapped as `"djJ8OTc2NDYx..."`).

```json
"djJ8OTc2NDYx..."
```

* `type=0` is USER, `type=2` is ADMIN.
* `expiry` is in seconds (1800 = 30 minutes).

> When to use: server-side APIs, signed/secure player embeds, upload/edit tasks that your backend coordinates. Scope privileges to the minimum required for each session.


### Bootstrap a base KS with session.startWidgetSession

```bash
curl -X POST "$KALTURA_SERVICE_URL/service/session/action/startWidgetSession" \
  -d "widgetId=_$KALTURA_PARTNER_ID" \
  -d "format=1"
```

* `widgetId` is `_<partnerId>` (underscore prefix).
* The response JSON contains `{ "result": { "ks": "&lt;WIDGET_KS_STRING&gt;", ... } }`.

> This will be used as initial session for AppTokens, or for non-authenticated light sessions such as anonymous player embeds (generated by the player itself when a KS is not provided).


### AppTokens → Privileged KS with appToken.startSession

High level flow:

1.	Create & store an Application Token (this action is performed once by the account admin to provide API access to a 3rd party trusted-scope partner. This step basically provisions an application security scope). See the [AppTokens Guide](/docs/getting-started/authentication/app-tokens-overview) for full details.
2.	Get a base KS (e.g., widget session).
3.	Compute tokenHash = HASH( baseKS + token ) with the same hash type as the app token.
4.	Call appToken.startSession(tokenId, tokenHash, ...) to receive the privileged KS.

> Keep the token and hashing strictly server-side.
> `sessionPrivileges` and `sessionUserId` are locked at token creation and enforced on every session minted from the token. Configure them at creation time.

**Step 1 -- Get a widget (base) KS:**

```bash
curl -X POST "$KALTURA_SERVICE_URL/service/session/action/startWidgetSession" \
  -d "widgetId=_$KALTURA_PARTNER_ID" \
  -d "format=1"
```

Save the returned `result.ks` value as `WIDGET_KS`.

**Step 2 -- Compute the token hash:**

Compute `tokenHash = SHA256(WIDGET_KS + APP_TOKEN_VALUE)` using your language's crypto library. The hash algorithm must match what was set when the Application Token was created (SHA256 is recommended).

For example, in a shell:

```bash
TOKEN_HASH=$(echo -n "$\{WIDGET_KS\}$\{KALTURA_APP_TOKEN\}" | shasum -a 256 | awk '{print $1}')
```

**Step 3 -- Exchange for a privileged KS:**

```bash
curl -X POST "$KALTURA_SERVICE_URL/service/apptoken/action/startSession" \
  -d "ks=$WIDGET_KS" \
  -d "id=$KALTURA_APP_TOKEN_ID" \
  -d "tokenHash=$TOKEN_HASH" \
  -d "userId=testUser" \
  -d "type=0" \
  -d "expiry=1800" \
  -d "sessionPrivileges=sview:*" \
  -d "format=1"
```

* The response JSON contains the privileged KS in `result`.

> You can disable or delete tokens (`appToken.update` → status, or `appToken.delete`) immediately revoking the app's ability to mint KS.
