Skip to content

URL Shortener API V3

Create shortened links and vanity links through a URL shortener configured for your Sprinklr partner. Sprinklr provides its own shortening utility, spr.ly, and can also front third-party providers.

This guide covers both V3 Links operations and includes migration guidance for developers moving from the V2 URL Shortener APIs.


On this page

  1. Overview
  2. Base URL and environments
  3. Authentication
  4. Operations
  5. Field reference
  6. Worked examples
  7. Response format and status codes
  8. Migrating from V2
  9. Common tasks
  10. Best practices
  11. Troubleshooting
  12. Related articles

Overview

The URL Shortener API exposes two operations, and in practice you use them together.

OperationMethod and pathPurpose
Fetch shortenersGET /link/shortenersList the URL shorteners available to your partner
Shorten a URLPOST /link/shortenCreate a short link or a vanity link

Call GET /link/shorteners first. POST /link/shorten requires a urlShortenerId, and the shorteners list is where you obtain it. Cache the result, because the list changes only when an administrator adds or removes a shortener in Sprinklr.

The API produces two kinds of short link.

Standard short link. Send link and urlShortenerId. Sprinklr generates the link hash for you and the response carries campaignId: -11.

Vanity link. Additionally send name. That value becomes the link hash verbatim, so name: "SpringSale" produces a short link ending in /SpringSale. Vanity links carry campaignId: -10 and populate the domain field.

Vanity links require a shortener whose canUseForVanityLink field is true. Read that flag from GET /link/shorteners before you attempt a vanity link.

The name field is the vanity hash, not the name of the shortener. The shortener's own name is UrlShortener.name, returned by GET /link/shorteners, and it is never sent to POST /link/shorten. Send name only when you want a vanity link with that exact hash.


Base URL and environments

https://api3.sprinklr.com/{env}/api/v3/link/shorten
https://api3.sprinklr.com/{env}/api/v3/link/shorteners

Replace {env} with the environment your partner is provisioned on. The supported values are:

prod, prod0, prod2, prod3, prod4, prod5, prod6, prod8, prod11, prod12, prod15, prod16, prod17, prod18, prod19, prod21, prod25

Use the environment your API key was issued against. Calling a different environment returns 401 rather than redirecting. If you are unsure which environment applies, check the host you use to sign in to Sprinklr, or contact your Sprinklr account team.


Authentication

Both operations require two authentication headers. Send both on every request.

HeaderValueDescription
AuthorizationBearer {{accessToken}}Bearer token used to authenticate the user with the server
Key{{apiKey}}API key that authenticates your application with the server
Content-Typeapplication/jsonRequired on POST /link/shorten
Acceptapplication/jsonAcceptable response type

Only one access token and refresh token pair exists per API key at a time. Requesting a new pair invalidates the previous one. If two of your services shorten links, either issue them separate API keys or centralise token refresh behind a single component.


Operations

Fetch all available URL shorteners

GET /link/shorteners

Returns every URL shortener visible to the partner behind your credentials, as an array.

  • Parameters: none
  • Request body: none
  • Success: 200

Use this operation to obtain two things: the id you pass as urlShortenerId when shortening, and the canUseForVanityLink flag that tells you whether the shortener supports vanity links.

The response is returned in a single call and is scoped to your partner. Cache it at start-up rather than fetching it before every shortening request.

POST /link/shorten

Creates a short link using the specified shortener.

  • Request body: required
  • Required fields: link, urlShortenerId
  • Success: 201 Created

Each call creates a new short link. Posting the same link and urlShortenerId twice produces two short links with two distinct id values, so maintain your own mapping of original URL to short link if you need to avoid duplicates.

Store id, linkHash, and shortLink from the response at creation time. These values are returned once, when the link is created.


Field reference

Request body for POST /link/shorten

FieldTypeRequiredDescription
linkstringYesThe URL to be shortened. Provide a fully qualified URL including the scheme
urlShortenerIdstringYesThe URL shortener to use. Obtain this from GET /link/shorteners
namestringNoUnique name or URL hash. When supplied, it becomes the link hash, producing a vanity link
descriptionstringNoDescription of the URL being shortened

URL shortener object

Returned as an array by GET /link/shorteners.

FieldTypeDescription
idstringID of the shortener. Pass this as urlShortenerId when shortening
namestringName of the shortener
providerstringShortener service provider
canUseForVanityLinkbooleanWhether the shortener can create vanity links

Treat a missing canUseForVanityLink as false rather than assuming vanity support. Select shorteners by name for human-facing choices and by provider when behaviour depends on the underlying service. Keep the selection configurable rather than hard-coding an id, because shortener IDs differ across environments and partners.

Returned as data by POST /link/shorten.

FieldTypeDescription
idinteger (int64)Short link ID
urlShortenerIdstringThe URL shortener that was used
linkHashstringUnique hash for the shortened link
originalLinkstringThe original URL that was shortened
shortLinkstringThe short URL. This is the value you publish
campaignIdinteger (int64)-10 for vanity links, -11 for links shortened directly
descriptionstringShort URL description
domainstringDomain used to shorten the link
providerstringURL provider used for shortening
createdTimeinteger (int64)Creation time of the short link
modifiedTimeinteger (int64)Last modified time of the short link
archivedbooleanWhether the short link is archived
postIdinteger (int64)Post ID the link is associated with

Six fields are consistently present on a creation response: id, urlShortenerId, linkHash, originalLink, shortLink, and campaignId. domain is additionally returned for vanity links. The remaining fields become populated later in a link's lifecycle, for example postId once the link is attached to a published post. Null-check any field beyond the six above.

Note the mixed identifier types: id is a 64-bit number, while urlShortenerId is a string ID. Do not store id in a field sized for a 24-character hexadecimal identifier.

How linkHash relates to your request

CaseWhat you sendResulting linkHashcampaignId
Standard linklink + urlShortenerIdSystem-generated alphanumeric token-11
Vanity linklink + urlShortenerId + nameExactly the name you sent-10

Read linkHash and shortLink directly from the response. Do not derive either value from id.


Worked examples

Replace {{accessToken}}, {{apiKey}}, and {env} with your own values.

List available shorteners

curl -X GET \
  'https://api3.sprinklr.com/{env}/api/v3/link/shorteners' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Accept: application/json'

Example response:

{
  "data": [
    {
      "id": "0000000000000000000000a1",
      "name": "Corporate spr.ly",
      "provider": "SPRINKLR",
      "canUseForVanityLink": true
    },
    {
      "id": "0000000000000000000000b2",
      "name": "Marketing Bitly",
      "provider": "BITLY",
      "canUseForVanityLink": false
    }
  ],
  "errors": []
}
curl -X POST \
  'https://api3.sprinklr.com/{env}/api/v3/link/shorten' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "link": "https://www.example.com/spring-campaign-landing-page",
    "urlShortenerId": "0000000000000000000000a1"
  }'

Example response, returned with status 201 Created:

{
  "data": {
    "id": 600000000,
    "urlShortenerId": "0000000000000000000000a1",
    "linkHash": "6003ZAI5v",
    "originalLink": "https://www.example.com/spring-campaign-landing-page",
    "shortLink": "https://spr.ly/6003ZAI5v",
    "campaignId": -11
  },
  "errors": []
}

Publish data.shortLink. Store data.id if you need to correlate the link later.

Send name as the hash you want, using a shortener where canUseForVanityLink is true.

curl -X POST \
  'https://api3.sprinklr.com/{env}/api/v3/link/shorten' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "link": "https://www.example.com/spring-campaign-landing-page",
    "urlShortenerId": "0000000000000000000000a1",
    "name": "SpringSale"
  }'

Example response:

{
  "data": {
    "id": 600000001,
    "urlShortenerId": "0000000000000000000000a1",
    "linkHash": "SpringSale",
    "originalLink": "https://www.example.com/spring-campaign-landing-page",
    "shortLink": "https://spr.ly/SpringSale",
    "campaignId": -10,
    "domain": "spr.ly"
  },
  "errors": []
}

linkHash echoes name, campaignId is -10, and domain is populated. All three confirm you received a vanity link rather than a standard one.

Vanity hashes occupy a shared namespace per shortener domain, so a given hash can be claimed only once. Choose names unlikely to collide, and handle a rejection by retrying with a different name.

End-to-end in Python

import requests

BASE = "https://api3.sprinklr.com/{env}/api/v3".format(env="prod0")
HEADERS = {
    "Authorization": "Bearer {{accessToken}}",
    "Key": "{{apiKey}}",
    "Content-Type": "application/json",
    "Accept": "application/json",
}


def get_shorteners():
    r = requests.get(BASE + "/link/shorteners", headers=HEADERS, timeout=30)
    r.raise_for_status()
    return r.json().get("data") or []


def pick_shortener(shorteners, need_vanity=False):
    for s in shorteners:
        if not need_vanity:
            return s
        if s.get("canUseForVanityLink") is True:
            return s
    raise RuntimeError("No suitable shortener is configured for this partner")


def shorten(link, shortener_id, name=None):
    body = {"link": link, "urlShortenerId": shortener_id}
    if name:
        body["name"] = name

    r = requests.post(BASE + "/link/shorten", headers=HEADERS,
                      json=body, timeout=30)

    if r.status_code not in (200, 201):
        r.raise_for_status()

    payload = r.json()
    errors = payload.get("errors") or []
    if errors:
        raise RuntimeError("Shortening failed: {}".format(errors))

    return payload["data"]


shorteners = get_shorteners()
chosen = pick_shortener(shorteners, need_vanity=True)
result = shorten(
    "https://www.example.com/spring-campaign-landing-page",
    chosen["id"],
    name="SpringSale",
)
print(result["shortLink"])

Two details are deliberate. The status check accepts both 200 and 201, and the errors array is inspected even on a success status.

End-to-end in JavaScript

const BASE = "https://api3.sprinklr.com/prod0/api/v3";
const HEADERS = {
  "Authorization": "Bearer {{accessToken}}",
  "Key": "{{apiKey}}",
  "Content-Type": "application/json",
  "Accept": "application/json",
};

async function getShorteners() {
  const res = await fetch(`${BASE}/link/shorteners`, { headers: HEADERS });
  if (!res.ok) throw new Error(`Fetch shorteners failed: ${res.status}`);
  const body = await res.json();
  return body.data ?? [];
}

async function shorten(link, urlShortenerId, name) {
  const payload = { link, urlShortenerId };
  if (name) payload.name = name;

  const res = await fetch(`${BASE}/link/shorten`, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify(payload),
  });

  if (res.status !== 200 && res.status !== 201) {
    throw new Error(`Shorten failed: ${res.status}`);
  }

  const body = await res.json();
  if (body.errors?.length) {
    throw new Error(`Shorten failed: ${JSON.stringify(body.errors)}`);
  }
  return body.data;
}

const shorteners = await getShorteners();
const vanityCapable = shorteners.find((s) => s.canUseForVanityLink === true);
const link = await shorten(
  "https://www.example.com/spring-campaign-landing-page",
  vanityCapable.id,
  "SpringSale",
);
console.log(link.shortLink);

Response format and status codes

Response envelope

Every Sprinklr V3 response is wrapped in a standard envelope:

{
  "data": { },
  "errors": [ ]
}

GET /link/shorteners returns an array in data. POST /link/shorten returns a single object in data.

Each entry in errors contains:

FieldTypeDescription
idstringError identifier
codestringError code
messagestringHuman-readable message

Bind your client to this envelope, and inspect the errors array even when the HTTP status indicates success.

Status codes

CodeMeaningHandling
200SuccessReturned by GET /link/shorteners
201CreatedReturned by POST /link/shorten on success
400Bad requestA required field is missing, the URL is malformed, or the vanity name was rejected
401UnauthorizedExpired token, wrong environment, or a missing authentication header
403ForbiddenYour user lacks permission for the shortener, or the partner is not entitled
404Not foundTypically an unrecognised urlShortenerId

Accept both 200 and 201 as success on POST /link/shorten, or check for any 2xx.

Rate limiting is applied at the Sprinklr API gateway across the platform. Implement retry with exponential backoff for 429 and 5xx responses, and honour the Retry-After header when it is present. Because shortening is not idempotent, retry only on network-level failures and on 429, and be aware that retrying after a timeout may create a second link.

About error messages

Validation errors for shortening are surfaced from the external shortening provider rather than generated by Sprinklr. This has three practical consequences:

  • Error message text and codes are not stable across providers. A partner using Bitly and a partner using spr.ly can receive different error bodies for the same mistake.
  • Branch your error handling on the HTTP status code rather than on the message text.
  • Log the full errors array and surface the message to an operator rather than attempting to parse it.

Migrating from V2

The short version

Change v2 to v3 in the path. For most integrations, that is the entire migration.

V2V3
ShortenPOST /{env}/api/v2/link/shortenPOST /{env}/api/v3/link/shorten
List shortenersGET /{env}/api/v2/link/shortenersGET /{env}/api/v3/link/shorteners
Request fieldslink, urlShortenerId, nameUnchanged
Required fieldslink, urlShortenerIdUnchanged
Response envelope{data, errors}Unchanged
Authentication headersAuthorization, KeyUnchanged
Success status on shorten200201

The two things that genuinely differ

Success status code. V2 returned 200 on shortening. V3 returns 201 Created. A client written as if (status === 200) will treat a successful V3 creation as a failure. This is the most likely cause of a broken migration. Widen the check to accept 200 and 201, or accept any 2xx.

Link hash format for standard links. In V2, the standard-link linkHash was the decimal string form of the numeric id, for example id: 101612830 with linkHash: "101612830". In V3, standard links return an alphanumeric token unrelated to the id. If any code derives one value from the other, or validates that linkHash is numeric, update it to read linkHash and shortLink directly from the response.

Vanity links are unaffected, because their hash has always been the name you supply.

What did not change

Request field names and semantics, the required field set, the {data, errors} envelope, the campaignId sentinels (-10 for vanity, -11 for standard), authentication, and the vanity-capability rule are all identical. Error responses are also unchanged, because validation errors originate from the external shortening provider in both versions.

Migration checklist

  1. Change api/v2 to api/v3 on both endpoints.
  2. Widen the success check on POST /link/shorten to accept 201.
  3. Remove any code that derives linkHash from id or assumes linkHash is numeric.
  4. Add null checks for domain, createdTime, modifiedTime, provider, archived, and postId.
  5. Continue inspecting the errors array on success statuses.
  6. Re-verify vanity flows against a shortener where canUseForVanityLink is true.

Common tasks

Shorten a link for a scheduled campaign post

Fetch the shortener list once at start-up and cache it. For each URL, call POST /link/shorten with link and the cached urlShortenerId, then publish data.shortLink. Store data.id and data.linkHash alongside your campaign record so reporting can be correlated later.

Select a shortener where canUseForVanityLink is true, then post with name set to the hash you want. Confirm success by checking that data.linkHash equals the name you sent and that campaignId is -10. If the hash comes back different, you did not receive the vanity link you requested, so do not publish it as one.

Expose a thin wrapper over POST /link/shorten and maintain your own mapping from original URL to short link. Check your mapping first and call Sprinklr only on a miss. This keeps your short-link inventory stable and avoids creating a new link each time the same URL is submitted.

Choose between multiple configured shorteners

GET /link/shorteners returns name and provider for each entry. Use name for human-facing selection and provider when behaviour depends on the underlying service. Keep the choice configurable so the same code works across environments and partners.


Best practices

  • Cache the shorteners list. It changes only when an administrator adds or removes a shortener. Fetch it at start-up rather than before every shortening call.
  • Persist the creation response. Store id, linkHash, and shortLink when the link is created. These values are returned at creation time.
  • Accept 200 and 201 as success on shortening.
  • Null-check optional fields. Depend only on id, urlShortenerId, linkHash, originalLink, shortLink, and campaignId.
  • Read the scheme from shortLink. Embed the returned string as-is rather than reconstructing the URL from domain and linkHash.
  • Deduplicate before retrying. Shortening is not idempotent, so a retry after a timeout can create a duplicate link.
  • Check canUseForVanityLink before requesting a vanity link, and treat a missing value as false.
  • Do not look up campaignId values of -10 or -11. These are sentinel values indicating a vanity or standard link, not references to a real campaign.
  • Keep shortener IDs in configuration, not in code, because they differ across environments and partners.

Firebase shorteners. Google deprecated its Firebase URL shortener, and Firebase shorteners are no longer supported in Sprinklr effective 25 August 2025. If your integration selects a shortener by provider, ensure it does not target Firebase.


Troubleshooting

SymptomLikely causeResolution
401 on every callWrong {env}, expired access token, or a missing Key headerConfirm the environment, refresh the token, and send both authentication headers
400 with an unclear messageA required field is missing, or the provider rejected the requestConfirm link and urlShortenerId are both present and that link includes a scheme
404 on shorteningurlShortenerId does not exist or is not visible to your userRe-fetch GET /link/shorteners and use an id from that response
Vanity name ignored, standard hash returnedThe shortener does not support vanity linksCheck canUseForVanityLink and select a different shortener
Vanity request rejectedThe hash is already claimed on that domainRetry with a different name
Client fails to deserialize the responseClient bound to the inner object rather than the envelopeBind to {data, errors} and read the payload from data
Duplicate short links after a retryShortening is not idempotentDeduplicate against your own mapping before retrying
Success status but nothing usable in dataAn error was returned alongside a success statusInspect the errors array on every response

Getting started

Reference

V2 documentation

Product documentation