Skip navigation

Folder Sharing via API

Updated: 31.08.2026
Open as Markdown

Sharing opens access to a folder through a link. The recipient needs no Kinescope account and no workspace invitation — just the link and, if you set one, a password.

The /v1/shares endpoints do the same thing as the Share button in the dashboard: they create a link, set a password and an expiry date, rotate the link, and revoke access. This article shows how to call them from your code. Authorization, response format, and the general shape of errors are covered in the general API guidelines .

  • Your LMS or CRM grants access automatically. A student pays for a course, your backend creates a share for the course folder and emails the link.
  • Access is temporary. A contractor works with the footage until the shoot ends: you set expires_at and the link stops working on its own.
  • The link leaked. A single reset-token call issues a new address and keeps every setting, while the old address stops working right away.
  • A subscription ended. DELETE revokes the share and closes access for everyone you sent it to.

If at least one of these sounds familiar, read on.

How a share works

  1. You create a share for a folder and get back a share object: share_id for later calls, a token, and a ready-made link.
  2. The link looks like https://kinescope.io/sh/{token}. The token is 22 characters computed from share_id, so you don’t need to store it separately.
  3. A folder can have only one active share. A second POST for the same folder returns 409.
  4. You change the settings — password, dates, downloads, name — with PATCH, and they take effect immediately.
  5. Access closes in two ways: reset-token changes the link and keeps the settings, DELETE revokes the share for good.

Now let’s go through the calls one by one.

What you need before the first request

  • A workspace API token. Pass it in the Authorization: Bearer YOUR_API_TOKEN header.
  • A paid plan. On the free plan, creating a share returns 403 with code 403001.
  • The entity_id of a folder. Only a folder can be shared. For a video or any other object, the API returns 400 with code 400001.
Important: the password field comes back in plain text. Don’t pass the sharing response to the browser as is — use has_password when all you need is to show that a password is set.

POST https://api.kinescope.io/v1/shares

curl -X POST 'https://api.kinescope.io/v1/shares' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "entity_id": "5b8a54a1-1f4f-4a5f-9a3a-2a4b0e2f1c77",
    "display_name": "Python course — cohort 12",
    "password": "python-2026",
    "allow_download": true,
    "expires_at": "2026-12-01T00:00:00Z"
  }'

Request body fields:

FieldTypeRequiredDescription
entity_idUUIDyesThe folder you open access to
display_namestringnoShare name, up to 255 characters
passwordstringnoPassword for entry, at least 3 characters
allow_downloadbooleannoAllow file downloads, false by default
starts_atRFC3339noThe moment the link starts working
expires_atRFC3339noThe moment the link stops working

Dates are converted to UTC. expires_at must be in the future, and starts_at must be earlier than expires_at. Otherwise the API returns 422.

Response 200 OK:

{
  "data": {
    "share_id": "9f1d3c02-77a0-4f5e-8b26-1e0a5d3c8b41",
    "entity_id": "5b8a54a1-1f4f-4a5f-9a3a-2a4b0e2f1c77",
    "workspace_id": "0c1b7a94-3f2e-4d6c-9a11-77c1f2b3d4e5",
    "display_name": "Python course — cohort 12",
    "password": "python-2026",
    "allow_download": true,
    "is_active": true,
    "starts_at": null,
    "expires_at": "2026-12-01T00:00:00Z",
    "created_at": "2026-08-31T12:38:38.475095Z",
    "updated_at": null,
    "token": "kDAcY15owhyW1RQaFq14rc",
    "link": "https://kinescope.io/sh/kDAcY15owhyW1RQaFq14rc",
    "has_password": true
  }
}

Give the recipient the link and keep the share_id: every other call needs it.

Reading the settings of an existing share

If you have the share_id, request the share directly:

curl 'https://api.kinescope.io/v1/shares/9f1d3c02-77a0-4f5e-8b26-1e0a5d3c8b41' \
  -H 'Authorization: Bearer YOUR_API_TOKEN'

If you only know the folder, look the share up by it:

curl 'https://api.kinescope.io/v1/shares/entity/5b8a54a1-1f4f-4a5f-9a3a-2a4b0e2f1c77' \
  -H 'Authorization: Bearer YOUR_API_TOKEN'

Both requests return only an active share, and the same object as creation does. A revoked share is not found by share_id or by entity_id.

Changing the password, dates, and downloads

PATCH https://api.kinescope.io/v1/shares/{share_id}

Send only the fields you are changing. The link stays the same.

curl -X PATCH 'https://api.kinescope.io/v1/shares/9f1d3c02-77a0-4f5e-8b26-1e0a5d3c8b41' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "password": "",
    "allow_download": false,
    "expires_at": "2027-01-15T00:00:00Z"
  }'

Fields have three states, and an empty value differs from a missing one:

What you sendWhat happens
Field not sentThe value stays unchanged
"password": "new-one"The password is set or changed
"password": ""The password is removed and entry becomes free
"display_name": ""The custom name is removed
"starts_at": null or "expires_at": nullThe date restriction is removed
"expires_at": "2027-01-15T00:00:00Z"The date is set; it must be in the future
Changing or removing the password closes open viewer sessions. Access with the old password stops immediately — anyone who already opened the link has to enter again.

The response is the full share object with the new values.

Did the link reach the wrong person? Rotate it:

curl -X POST 'https://api.kinescope.io/v1/shares/9f1d3c02-77a0-4f5e-8b26-1e0a5d3c8b41/reset-token' \
  -H 'Authorization: Bearer YOUR_API_TOKEN'

Kinescope revokes the current share and creates a new one with the same password, dates, name, and download permission. The old link stops working right away.

Important: the response holds a new share with a new share_id, token, and link. Replace the stored share_id — every following request with the old one returns 404.

You can rotate the token only on an active share. On a revoked one, the call returns 409 with code 409297 — create a new share for the same folder instead.

Revoking access

DELETE https://api.kinescope.io/v1/shares/{share_id}

curl -X DELETE 'https://api.kinescope.io/v1/shares/9f1d3c02-77a0-4f5e-8b26-1e0a5d3c8b41' \
  -H 'Authorization: Bearer YOUR_API_TOKEN'

Response 200 OK:

{
  "data": {
    "success": true
  }
}

Revocation is final. To open access again, create a new share for the same folder — the link will be different.

Sharing errors

Errors arrive in the common format: an error object with a numeric code and a message.

HTTPerror.codeWhen it happens
400400001entity_id points to something other than a folder
403100103The token has no rights to this folder
403403001Sharing is not available on the free plan
409409001The folder already has an active share
409409297The share is revoked, so reset-token is unavailable
422422001Parameters failed validation

Example response to an attempt to share a video:

{
  "error": {
    "code": 400001,
    "message": "only a folder can be shared"
  }
}

Example response to an expires_at in the past:

{
  "error": {
    "code": 422001,
    "message": "request parameters didn't validate"
  }
}

When the error maps to a specific field — a password shorter than three characters, for example — the response also carries an invalid_params array with the field name and the reason.

If the resource is not found, the API responds like this:

HTTP/1.1 404 Not Found
Content-Type: application/json

{ "error" : { "code" : 400404, "message" : "not found" } }

Example: granting folder access from your backend

This function creates a share with an expiry date and returns the share_id and the ready-made link:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"time"
)

type createShareRequest struct {
	EntityID  string     `json:"entity_id"`
	Password  string     `json:"password,omitempty"`
	ExpiresAt *time.Time `json:"expires_at,omitempty"`
}

type shareResponse struct {
	Data struct {
		ShareID string `json:"share_id"`
		Link    string `json:"link"`
	} `json:"data"`
}

// CreateShare opens access to folder folderID for the ttl period.
func CreateShare(apiToken, folderID, password string, ttl time.Duration) (string, string, error) {
	expiresAt := time.Now().UTC().Add(ttl)
	body, err := json.Marshal(createShareRequest{
		EntityID:  folderID,
		Password:  password,
		ExpiresAt: &expiresAt,
	})
	if err != nil {
		return "", "", err
	}

	req, err := http.NewRequest(http.MethodPost, "https://api.kinescope.io/v1/shares", bytes.NewReader(body))
	if err != nil {
		return "", "", err
	}
	req.Header.Set("Authorization", "Bearer "+apiToken)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return "", "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", "", fmt.Errorf("kinescope: share not created, status %d", resp.StatusCode)
	}

	var out shareResponse
	if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
		return "", "", err
	}

	// You need share_id for PATCH, reset-token, and DELETE — store it.
	return out.Data.ShareID, out.Data.Link, nil
}

What’s next?

  1. General API guidelines — authorization, response format, request limits
  2. File upload via API — fill the folder before you share it
  3. Authorization backend — access control for individual videos by your system’s rules

Still have questions? Write to the support chat within the Kinescope interface — our specialists will help!