Skip to main content
Apps can offer a fixed, read-only slice of their content to other apps. Each slice is a share, named share:<provider>.<feature>: share:blog.posts is the blog app’s list of published posts. Your app lists the shares it wants in cskn.json, asks the user, and reads them with the SDK.

Whose permission counts

Every share has a subject: whose content it returns. The subject decides who has to say yes. The platform applies the owner’s visibility before anything comes back. If someone shows an app to followers only, a visitor who doesn’t follow them gets nothing. Blocked people and suspended accounts are left out too. What a share returns is safe to show as it is.

Declaring what you want

List the shares in the crossApp field of your app’s cskn.json. Each deploy publishes the list:
A share that isn’t listed can’t be asked for or read, even if a user granted it to your app before. Listing one is only a request. The user’s grant is what lets you read it. The deploy warns you about a share its provider doesn’t offer, or one that is limited to some apps. It still publishes the list, because the provider may add the share later.
cskn.json is the only source. If you remove a share from crossApp, the next deploy stops your app from reading it.

Reading

useCrossApp(provider, feature, options) reads a share page by page. It is a TanStack Query useInfiniteQuery.
string
required
The app that offers the share, for example blog.
string
required
The share’s name within that app, for example posts.
string
Whose content to read. Required for a user share.
number
Page size. The platform clamps it: 20 by default, at most 50, and a share can set lower bounds.
boolean
default:"true"
Set to false to hold the request.
T[]
Every page loaded so far, flattened. Typed per share; see Typing a share.
CrossAppError | null
The platform’s reason for refusing, or null. A refusal is not retried.
function / boolean
From useInfiniteQuery. Load more while hasNextPage is true.
A refusal is the normal case on most profiles: the owner hasn’t shared, or shows the app to some people only. If you show a share on someone’s user page, draw nothing when it is refused rather than an error. Without React, use readCrossApp(provider, feature, { username, limit, cursor }). It resolves to { items, nextCursor }. Pass nextCursor back as cursor for the next page. It is null on the last page.

Signed-out visitors

A user share can be read with no session, so a visitor to a user page sees the owner’s content. The SDK names your app on the request. The platform then returns only what the owner shows to everyone. A self or grantors share needs a signed-in user.

Asking for a share

useCrossAppAccess(scopes) returns what the user said to each share and a request function that opens the consent screen.
string | string[]
The shares this screen is about. Leave it out to cover every share in your cskn.json.
boolean
true when every share in scope is granted. false while loading.
CrossAppAccessShare[]
One entry per share: scope, subject, description ({ en, tr }), granted, providerName, and providerActivated (whether the user has the provider app turned on).
string[]
The shares in scope the user hasn’t granted.
(only?: string[]) => Promise<CrossAppRequestResult>
Opens the consent screen for the missing shares, or for only. Call it from a tap or a click.
(only?: string[]) => Promise<{ changed: boolean }>
Gives back the granted shares in scope, or only.
request never rejects. It resolves to { granted, declined, error? }:
  • granted lists the shares that are granted now, including ones granted before.
  • declined lists the rest.
  • error is set only when the user wasn’t asked.
The user saying no is not an error. Shares granted before aren’t asked again. After the screen closes, every cross-app query refreshes. Ask for what the screen in front of the user needs, not for everything in your cskn.json. For a self share, asking is how you get to read it. For user and grantors shares, asking is how the viewer shares their own content with your app. Without React, use requestCrossApp(scopes) and getCrossAppAccess().

Giving a share back

revokeCrossApp(scopes), or revoke from the hook, stops your app from holding a share for the signed-in user. Use it for an in-app “stop showing this” switch. It can only narrow your app’s access. Granting always goes through the consent screen. Users can also take shares back themselves. On mobile and desktop they do it under Profile → App access. Your app sees that as granted: false the next time it reads the access.

Shares you can use

One person’s published posts, newest first. Drafts never appear. Default page 5, at most 20.
One person’s latest public photos. A private photo never appears, not even to its owner. Default page 12, at most 30.
Image URLs are signed and expire. Show them, but never store them.
getCrossAppCatalog(provider) lists what a provider offers: each share’s feature, subject and description, and restricted when only some apps may ask for it.

Typing a share

readCrossApp and useCrossApp type items from the CrossShareMap interface. The shares above are already in it as CrossBlogPost and CrossPhoto. For any other share, add its type yourself:
A share that isn’t in the map reads as unknown.

Refusals

crossAppError(error) returns { code, status, message } for a refused read, or null for anything else, such as a network failure.