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 and partner-managed users 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. On first use, Signal provisions a dedicated partner-managed hosted profile for that workspace and external identifier. It has no password and never matches, links, or signs into an existing Ceyo account by email.login_links:manage, and the requested project or location package must enable Customer access through pricing.frontend_delivery_enabled. This single entitlement enables both hosted Signal UI and redirect login links. Signal verifies the package entitlement and embedded access 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 through its dedicated partner-managed account. 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.
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. 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).
redirect_path controls the first page opened inside Signal. return_url controls where the user may return afterward. Signal does not accept arbitrary origins, JavaScript URLs, protocol-relative URLs, or URLs containing credentials. After sign-in, hosted Signal displays a Return to partner action only when a validated return_url was supplied.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/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 | customer_access_not_enabledThe API key lacks login_links:manage, the package does not enable Customer access, or the embedded identity lacks access to the requested scope.
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.