Redirect login links
Send an embedded identity into hosted Signal with a short-lived, one-time URL.
viewer is read-only, editor manages supported operational features, and admin additionally manages settings within the granted project or location. A login link authenticates the identity and never elevates its role.external_user_id resolves an embedded identity in the API key’s workspace. Redemption creates a hosted Platform session directly for that identity. Signal does not create a normal Ceyo user, mirror its grants, or match an existing account by email.login_links:manage, and the requested project or location package must be active. The workspace must also have hosted white-label enabled. Signal verifies the API key, package, identity, and grant both when the link is created and when it is used. Return URLs must use an exact HTTPS origin in the API key’s allowed_origins; redirect paths stay within hosted Signal.POSTCreate redirect login link
/login-linksCreates a one-time hosted Signal login URL for an embedded identity and a project or location it can access.
Create redirect login link
/login-linksRequest body
external_user_idstringRequired external identifier of the embedded identity that will sign in directly. Maximum: 200 characters.
project_idproject UUID | project external IDRequired project identifier. The embedded identity must already have access to this project.
location_idlocation UUID | location external ID | nullOptional location within the project. When supplied, the embedded identity must have access to this location.
landingauto | projects | locations | nullOptional simple landing choice. auto applies resource-count routing, projects opens the Projects list, and locations opens the selected project’s Locations list. Cannot be combined with location_id or redirect_path.
redirect_pathstring | nullOptional relative path to open in hosted Signal after sign-in. Must begin with one slash and cannot contain a scheme, host, backslash, or protocol-relative URL. Defaults to the selected project or location home.
return_urlhttps URL | nullOptional URL shown as the safe return destination from Signal. It overrides the workspace default return URL. Its origin must be registered for the API key; fragments and embedded credentials are rejected.
expires_inintegerOptional lifetime in seconds. Defaults to 900 (15 minutes); minimum: 60; maximum: 3,600 (1 hour).
landing: "auto", landing: "projects", or landing: "locations" for common destinations. Use redirect_path for an advanced internal page; it cannot be combined with landing. return_url controls where the user may return afterward and overrides the workspace default. Signal does not accept arbitrary origins, JavaScript URLs, protocol-relative URLs, path traversal, or URLs containing credentials. After sign-in, hosted Signal displays the workspace-configured return action when either a validated return_url or a workspace default return URL is available.Response envelope
login_link:LoginLinkThe requested or resulting login link.
LoginLink
iduuidStable login link identifier used for lifecycle requests.
urlstring | nullHosted Signal sign-in URL. Returned only when the link is created; lifecycle responses return null.
statuspending | used | expired | revokedCurrent one-time login link status.
expires_atdatetimeTime the pending link expires, in ISO 8601 format.
used_atdatetime | nullTime the link was successfully used, or null if it was not used.
created_atdatetimeTime the link was created, in ISO 8601 format.
Request and response
curl --request POST \
--url 'https://api.signal.ceyo.ai/v1/login-links' \
--header 'Authorization: Bearer ceyo_platform_...' \
--header 'Content-Type: application/json' \
--data '{
"external_user_id": "customer-user-4821",
"project_id": "partner-project-acme",
"location_id": "a1308d14-149c-4dd7-a4c5-295ac9090f58",
"redirect_path": "/workspaces/{workspace_id}/projects/e6c96c98-d777-40e0-94ec-48931f57782f/locations/a1308d14-149c-4dd7-a4c5-295ac9090f58/visibility",
"return_url": "https://portal.partner.example/customers/4821",
"expires_in": 900
}'HTTP/1.1 201 Created
{
"login_link": {
"id": "7a73ed11-d5dc-4b6a-8681-d9e571d2a991",
"url": "https://signal.ceyo.ai/login-links/7a73ed11-d5dc-4b6a-8681-d9e571d2a991?token=ceyo_login_...",
"status": "pending",
"expires_at": "2026-07-31T10:15:00Z",
"used_at": null,
"created_at": "2026-07-31T10:00:00Z"
}
}ErrorsResponse format and status codes
Error response envelope
errorErrorStructured error payload.
Error
codestringStable snake_case code suitable for programmatic handling.
messagestringHuman-readable explanation of the failure.
detailsobject | array | nullStructured validation or request context when available.
request_idstringIdentifier to provide when requesting support.
{
"error": {
"code": "invalid_api_key",
"message": "The Bearer API key is invalid.",
"details": null,
"request_id": "req_01K1F8M7QX4R2V9N6Y3Z0A5BCT"
}
}Status codes
400invalid_requestThe JSON body was not provided, is malformed, or contains an unknown field.
401invalid_api_keyThe Bearer API key is absent or invalid.
403forbidden | white_label_not_enabled | package_not_activeThe API key lacks login_links:manage, the embedded identity lacks an active grant to the requested scope, hosted white-label is disabled for the workspace, or the assigned package is not active.
404not_foundThe embedded identity, project, or location was not found for this API key.
422validation_failedAn identifier, expiry, redirect path, or return URL does not meet the documented constraints.
429rate_limit_exceededToo many login links were created or too many requests were made.
GETGet login link
/login-links/{login_link_id}Returns the current state of a login link without changing it.
Get login link
/login-links/{login_link_id}Path parameters
login_link_iduuidLogin link identifier returned by the create endpoint.
Response envelope
login_link:LoginLinkThe requested or resulting login link.
LoginLink
iduuidStable login link identifier used for lifecycle requests.
urlstring | nullHosted Signal sign-in URL. Returned only when the link is created; lifecycle responses return null.
statuspending | used | expired | revokedCurrent one-time login link status.
expires_atdatetimeTime the pending link expires, in ISO 8601 format.
used_atdatetime | nullTime the link was successfully used, or null if it was not used.
created_atdatetimeTime the link was created, in ISO 8601 format.
pending, used, expired, or revoked and never changes the link. Used, expired, and revoked are terminal states. A terminal link cannot be used, revoked, or reactivated.Request and response
curl --request GET \
--url 'https://api.signal.ceyo.ai/v1/login-links/7a73ed11-d5dc-4b6a-8681-d9e571d2a991' \
--header 'Authorization: Bearer ceyo_platform_...'{
"login_link": {
"id": "7a73ed11-d5dc-4b6a-8681-d9e571d2a991",
"url": null,
"status": "pending",
"expires_at": "2026-07-31T10:15:00Z",
"used_at": null,
"created_at": "2026-07-31T10:00:00Z"
}
}ErrorsResponse format and status codes
Error response envelope
errorErrorStructured error payload.
Error
codestringStable snake_case code suitable for programmatic handling.
messagestringHuman-readable explanation of the failure.
detailsobject | array | nullStructured validation or request context when available.
request_idstringIdentifier to provide when requesting support.
{
"error": {
"code": "invalid_api_key",
"message": "The Bearer API key is invalid.",
"details": null,
"request_id": "req_01K1F8M7QX4R2V9N6Y3Z0A5BCT"
}
}Status codes
400invalid_requestThe login_link_id is malformed.
401invalid_api_keyThe Bearer API key is absent or invalid.
403forbiddenThe API key cannot manage login links.
404not_foundThe login link was not found for this API key.
429rate_limit_exceededToo many requests were made.
DELETERevoke login link
/login-links/{login_link_id}Revokes a pending login link and returns its terminal revoked state.
Revoke login link
/login-links/{login_link_id}Path parameters
login_link_iduuidLogin link identifier returned by the create endpoint.
Response envelope
login_link:LoginLinkThe requested or resulting login link.
LoginLink
iduuidStable login link identifier used for lifecycle requests.
urlstring | nullHosted Signal sign-in URL. Returned only when the link is created; lifecycle responses return null.
statuspending | used | expired | revokedCurrent one-time login link status.
expires_atdatetimeTime the pending link expires, in ISO 8601 format.
used_atdatetime | nullTime the link was successfully used, or null if it was not used.
created_atdatetimeTime the link was created, in ISO 8601 format.
revoked and returns 200 OK. Used, expired, and revoked links remain unchanged and return 409 login_link_not_pending. Revoked links cannot be used or reactivated.Request and response
curl --request DELETE \
--url 'https://api.signal.ceyo.ai/v1/login-links/7a73ed11-d5dc-4b6a-8681-d9e571d2a991' \
--header 'Authorization: Bearer ceyo_platform_...'{
"login_link": {
"id": "7a73ed11-d5dc-4b6a-8681-d9e571d2a991",
"url": null,
"status": "revoked",
"expires_at": "2026-07-31T10:15:00Z",
"used_at": null,
"created_at": "2026-07-31T10:00:00Z"
}
}ErrorsResponse format and status codes
Error response envelope
errorErrorStructured error payload.
Error
codestringStable snake_case code suitable for programmatic handling.
messagestringHuman-readable explanation of the failure.
detailsobject | array | nullStructured validation or request context when available.
request_idstringIdentifier to provide when requesting support.
{
"error": {
"code": "invalid_api_key",
"message": "The Bearer API key is invalid.",
"details": null,
"request_id": "req_01K1F8M7QX4R2V9N6Y3Z0A5BCT"
}
}Status codes
400invalid_requestThe login_link_id is malformed.
401invalid_api_keyThe Bearer API key is absent or invalid.
403forbiddenThe API key cannot manage login links.
404not_foundThe login link was not found for this API key.
409login_link_not_pendingThe link is used, expired, or revoked and remains in that terminal state.
429rate_limit_exceededToo many requests were made.