Building an Application
Integrate live video into your project. - API reference - Our component library
Building an Application
Integrate live video into your project. - API reference - Our component library
Self-Hosting
Run your own Streamplace infrastructure. - Installation guide
Contributing
Help improve Streamplace. - Development setup - Video signing
Support & Community
Get help and connect with other developers. - GitHub issues - Discord community
Handles can temporarily fail AT Protocol’s bidirectional verification after a
rename, domain change, or handle swap. Streamplace displays the account’s DID
instead of handle.invalid (or an absent handle), including chat, push and
Discord notifications, and keeps its stream, video, profile and share links
DID-addressable. A DID is not prefixed with @. API identity responses retain
the protocol’s handle.invalid sentinel; clients must apply the same display
and link fallback rather than treating it as a name.
Supported identifiers are did:plc and hostname-level did:web DIDs without
ports. Path-based did:web DIDs and the localhost-only encoded-port extension
are not supported by Streamplace.
The existing atproto sweep rechecks successfully indexed, active accounts
against the identity directory without using its cached answer. A corrected
handle or moved PDS is picked up when the next sweep reaches that account, even
if the node missed its firehose identity event. The default interval is six
hours, configured with --sweep-interval / SP_SWEEP_INTERVAL; 0 disables
periodic sweeps. Shorter intervals increase directory, DNS and PDS traffic.
Identity refresh updates only identity fields, preserving indexing progress.
Lookup failures leave the last known identity intact.
To refresh one account immediately, use its stable DID:
curl -X POST https://YOUR_NODE/xrpc/com.atproto.identity.refreshIdentity \ -H 'Content-Type: application/json' \ -d '{"identifier":"did:plc:YOUR_ACCOUNT"}'Refreshing an identity does not index an unknown account. Empty or invalid handles, and ambiguous cached handle claims, never select an arbitrary indexed account; use the DID while handle ownership is being repaired.
The stream websocket (/api/websocket/{streamer}) includes indexed Bluesky
profile metadata in the author objects on its views. Alongside did and
handle, an author can include displayName, pronouns, and avatar. The
text fields retain their indexed values; avatar is an HTTPS image URL, not a
blob reference:
https://cdn.bsky.app/img/avatar/plain/{authorDid}/{avatarBlobCid}@jpegLive chat events and reconnect snapshots use the same local profile index, including authors inside reply previews and pinned messages. The node uses the ordinary Bluesky profile, not Streamplace’s temporary go-live profile copy, and does not query a public AppView to fill these fields.
Treat the metadata as optional: an account may have no indexed profile or may not have set every field. A profile lookup failure does not drop the event. Already emitted views are not rewritten when a profile changes; newly built views and reconnect snapshots use the profile indexed at that time.
Chat messages (place.stream.chat.message) sent by Streamplace include the
sending device’s local UTC offset in createdAt, for example
2026-10-17T13:30:00.123-07:00. The offset is read at send time, including
daylight-saving adjustments; there is no account-wide time zone setting. Devices
set to UTC send +00:00. Existing records ending in Z remain valid.
The node preserves the original timestamp in the record and compares instants
for chat ordering and freshness. Consumers should parse RFC 3339 timestamps, not
compare their strings or assume a trailing Z.
The offset gives bots the sender’s local wall-clock time, not an IANA time zone
such as America/Los_Angeles. It cannot determine daylight-saving transitions
for future scheduling; ask for a named zone when those rules matter.