[{"data":1,"prerenderedAt":1541},["ShallowReactive",2],{"$fp-rOOnce7HPNUtPcdzeThQtCkMXnKIn3xRULGti4dac":3,"$fQsTeQwPELeuBajPd_NSlDyBIg5SdnSSfNPGVzyJPSt8":175},{"blueprints":4},[5,22,38,51,63,75,84,94,106,116,124,134,146,154,165],{"slug":6,"title":7,"summary":8,"category":9,"logo":10,"cover":11,"tags":12,"stats":15,"publishedAt":21},"bookmark-manager","Bookmark Manager","A private library of links you save yourself, from browser, phone or a browser's export, filed and tagged, with your own AI agent suggesting tidying.","productivity","\u002F_blueprints\u002Fbookmark-manager.logo.svg","\u002F_blueprints\u002Fbookmark-manager.cover.webp",[13,14],"agentic","single-user",{"entities":16,"capabilities":17,"journeys":18,"scenarios":19,"rules":20},7,15,3,37,18,"2026-10-07T14:20:29+03:00",{"slug":23,"title":24,"summary":25,"category":26,"logo":27,"cover":28,"tags":29,"stats":33,"publishedAt":21},"code-snippet-sharing","Code Snippet Sharing","Keep code snippets with their language, description and tags, share them by unlisted link or in public, fork others' public snippets, and revise code with kept history.","dev-tools","\u002F_blueprints\u002Fcode-snippet-sharing.logo.svg","\u002F_blueprints\u002Fcode-snippet-sharing.cover.webp",[30,31,32],"ai-assisted","multi-user","public",{"entities":34,"capabilities":35,"journeys":36,"scenarios":37,"rules":35},4,9,1,26,{"slug":39,"title":40,"summary":41,"category":9,"logo":42,"cover":43,"tags":44,"stats":45,"publishedAt":50},"content-feed-reader","Content Feed Reader","Follow feeds, catch up and keep worthwhile items in a private web or mobile library, and publish read-only collections for the web.","\u002F_blueprints\u002Fcontent-feed-reader.logo.svg","\u002F_blueprints\u002Fcontent-feed-reader.cover.webp",[32,14],{"entities":46,"capabilities":47,"journeys":48,"scenarios":49,"rules":17},6,20,2,39,"2026-08-04T15:46:50+03:00",{"slug":52,"title":53,"summary":54,"category":55,"logo":56,"cover":57,"tags":58,"stats":59,"publishedAt":21},"event-rsvp","Event RSVP","Create an event, share one invitation link, collect going, maybe and not going answers without guest accounts, keep a waitlist once it is full, and message the guests.","community","\u002F_blueprints\u002Fevent-rsvp.logo.svg","\u002F_blueprints\u002Fevent-rsvp.cover.webp",[30,31,32],{"entities":60,"capabilities":35,"journeys":48,"scenarios":61,"rules":62},5,33,11,{"slug":64,"title":65,"summary":66,"category":67,"logo":68,"cover":69,"tags":70,"stats":71,"publishedAt":21},"flashcard-app","Flashcard App","Build flashcard decks, study what is due with spaced repetition on the web or a phone, draft cards from pasted notes, and share decks for others to copy.","education","\u002F_blueprints\u002Fflashcard-app.logo.svg","\u002F_blueprints\u002Fflashcard-app.cover.webp",[30,31],{"entities":34,"capabilities":72,"journeys":48,"scenarios":73,"rules":74},14,29,13,{"slug":76,"title":77,"summary":78,"category":55,"logo":79,"cover":80,"tags":81,"stats":82,"publishedAt":21},"form-and-survey-builder","Form & Survey Builder","Build a form or survey, share it through a public link, collect answers from people without accounts, and review, summarize and export what came back.","\u002F_blueprints\u002Fform-and-survey-builder.logo.svg","\u002F_blueprints\u002Fform-and-survey-builder.cover.webp",[30,31,32],{"entities":46,"capabilities":20,"journeys":36,"scenarios":83,"rules":20},34,{"slug":85,"title":86,"summary":87,"category":9,"logo":88,"cover":89,"tags":90,"stats":91,"publishedAt":21},"habit-tracker","Habit Tracker","Define habits on a daily, chosen-day or weekly schedule, check them off, follow their streaks, pause one without losing it, and read an optional weekly reflection.","\u002F_blueprints\u002Fhabit-tracker.logo.svg","\u002F_blueprints\u002Fhabit-tracker.cover.webp",[30,14],{"entities":60,"capabilities":92,"journeys":48,"scenarios":93,"rules":17},12,30,{"slug":95,"title":96,"summary":97,"category":98,"logo":99,"cover":100,"tags":101,"stats":102,"publishedAt":21},"kanban-board","Kanban Board","Plan and track a small team's work on shared boards of columns and cards, with stalled work flagged and an AI agent proposing the next cards.","collaboration","\u002F_blueprints\u002Fkanban-board.logo.svg","\u002F_blueprints\u002Fkanban-board.cover.webp",[13,31],{"entities":35,"capabilities":103,"journeys":36,"scenarios":104,"rules":105},23,44,32,{"slug":107,"title":108,"summary":109,"category":9,"logo":110,"cover":111,"tags":112,"stats":113,"publishedAt":21},"notes-app","Notes App","Capture quick notes into an inbox, file them into notebooks, tag and link them, find them again, and let your own AI agent suggest where they belong.","\u002F_blueprints\u002Fnotes-app.logo.svg","\u002F_blueprints\u002Fnotes-app.cover.webp",[13,14],{"entities":46,"capabilities":74,"journeys":36,"scenarios":114,"rules":115},31,17,{"slug":117,"title":118,"summary":119,"category":98,"logo":120,"cover":121,"tags":122,"stats":123,"publishedAt":21},"polls-and-decisions","Polls & Decisions","Put a question to the team as a poll, vote and argue while it is open, and keep the outcome as a decision the team can look up.","\u002F_blueprints\u002Fpolls-and-decisions.logo.svg","\u002F_blueprints\u002Fpolls-and-decisions.cover.webp",[30,31],{"entities":60,"capabilities":62,"journeys":36,"scenarios":73,"rules":74},{"slug":125,"title":126,"summary":127,"category":26,"logo":128,"cover":129,"tags":130,"stats":131,"publishedAt":21},"public-status-page","Public Status Page","Publish a public page of your components and their current status, keep visitors informed through incidents and scheduled maintenance, and email confirmed subscribers every update an operator posts.","\u002F_blueprints\u002Fpublic-status-page.logo.svg","\u002F_blueprints\u002Fpublic-status-page.cover.webp",[30,31,32],{"entities":16,"capabilities":72,"journeys":36,"scenarios":132,"rules":133},28,19,{"slug":135,"title":136,"summary":137,"category":67,"logo":138,"cover":139,"tags":140,"stats":141,"publishedAt":21},"quiz-builder","Quiz Builder","Build quizzes of multiple-choice, true\u002Ffalse and short-answer questions, share them by link or with a class, score each learner's one attempt, and practice what was missed.","\u002F_blueprints\u002Fquiz-builder.logo.svg","\u002F_blueprints\u002Fquiz-builder.cover.webp",[30,31],{"entities":142,"capabilities":143,"journeys":48,"scenarios":144,"rules":145},10,22,45,24,{"slug":147,"title":148,"summary":149,"category":67,"logo":150,"cover":151,"tags":152,"stats":153,"publishedAt":21},"study-planner","Study Planner","Set dated study goals with estimated topics, get a schedule built around your weekly hours, log what you study, and let your AI agent propose revisions.","\u002F_blueprints\u002Fstudy-planner.logo.svg","\u002F_blueprints\u002Fstudy-planner.cover.webp",[13,14],{"entities":46,"capabilities":115,"journeys":48,"scenarios":83,"rules":103},{"slug":155,"title":156,"summary":157,"category":98,"logo":158,"cover":159,"tags":160,"stats":161,"publishedAt":21},"team-wiki","Team Wiki","Keep a team's knowledge in permissioned spaces of nested pages with revision history, find it by search, and let members' AI agents answer from it and suggest updates.","\u002F_blueprints\u002Fteam-wiki.logo.svg","\u002F_blueprints\u002Fteam-wiki.cover.webp",[13,31],{"entities":162,"capabilities":163,"journeys":48,"scenarios":164,"rules":47},8,16,41,{"slug":166,"title":167,"summary":168,"category":26,"logo":169,"cover":170,"tags":171,"stats":173,"publishedAt":21},"url-shortener","URL Shortener","Turn long addresses into short links on the web or through an API, disable them or let them expire, and see how often and where they are followed.","\u002F_blueprints\u002Furl-shortener.logo.svg","\u002F_blueprints\u002Furl-shortener.cover.webp",[172,32,14],"api",{"entities":46,"capabilities":142,"journeys":174,"scenarios":47,"rules":92},0,{"blueprint":176},{"slug":166,"publishedAt":21,"reportDigest":177,"logo":169,"cover":170,"report":178,"source":1538},"b7270ad94e1e4cdb868d57acd35292b883b7143f626003591839986ce8d89700",{"schemaVersion":179,"id":166,"title":167,"summary":168,"description":180,"category":26,"authors":181,"license":184,"intent":185,"supportingSections":186,"references":187,"referenceProfile":193,"tags":194,"languages":195,"generatedAt":197,"generator":198,"counts":201,"limitations":202,"model":210,"coverage":1533},"19.0.0","A link shortener for people who hand out web addresses: in posts, slides,\nprinted material and their own software. An Owner turns a long address into a\nshort link, with a slug the Product generates or one they choose, can point it\nsomewhere else, disable and enable it or give it an expiry, and sees how often\nand from where it is followed. Their own tools create links through an API with a key\nthe Owner issues.",[182],{"name":183},"pdd-kit","MIT","An address handed out in print, on slides or in someone else's post cannot be\ntaken back, so the person who handed it out needs a short name for it that\nthey control and that never changes meaning. Its Owner can change where it\nleads, disable it or let it expire, but nobody deletes it or gives its slug to\nanother link. Owners learn how their links travel without the Product learning\nwho followed them.",[],[188],{"kind":189,"role":190,"target":191,"title":192},"research","context","https:\u002F\u002Fgithub.com\u002Fitai-gendler\u002Fpdd-kit\u002Fblob\u002Fmain\u002Fblueprints\u002Furl-shortener\u002Freferences\u002Fassumptions.md","Shortener assumptions","portable",[172,32,14],[196],"en","2026-10-12",{"name":199,"version":200},"pdd-kit-cli","0.34.1",{"interfaces":48,"experiences":48,"screens":34,"domains":48,"entities":46,"capabilities":142,"capabilityScenarios":47,"journeys":174,"journeyScenarios":174,"businessRules":92,"variations":174},[203,204,205,206,207,208,209],"Every link lives under the Product's one short domain; an Owner cannot bring a domain of their own.","Links and API keys belong to one Owner's account. There are no teams, shared links or roles.","The API only creates links. Editing, disabling, enabling, analytics and API keys are on the web alone.","Analytics count follows and describe where they came from; they never tell Visitors apart, so there are no unique-visitor counts.","Links are never deleted; disabling one stops its redirect, and its slug is never given to another link.","An API key keeps the name it was created with; it is revoked, never edited.","The Owner signs in with an existing account, while Visitors follow short links without one; signing up and managing accounts are not part of this product.",{"taxonomies":211,"interfaces":225,"experiences":251,"screens":275,"domains":384,"entities":397,"capabilities":493,"capabilityScenarios":576,"journeys":1335,"journeyScenarios":1336,"businessRules":1337,"variations":1532},{"scenarioKinds":212},[213,217,221],{"id":214,"name":215,"description":216,"colorSlot":46},"edge","Edge case","An uncommon but expected path with a distinct observable outcome.",{"id":218,"name":219,"description":220,"colorSlot":36},"primary","Primary","The expected observable behavior path.",{"id":222,"name":223,"description":224,"colorSlot":18},"validation","Validation","Input the Product refuses while preserving the Actor's work.",[226,237],{"id":227,"title":228,"description":229,"type":172,"actorIds":230,"entryPoints":232,"languages":233,"intent":234,"supportingSections":235,"references":236},"shortener-api","Link API","The supported programmatic Interface through which an Owner's own tools create\nlinks in the Owner's account, authenticated by one of the Owner's API keys.\nIt creates links only.",[231],"api-client",[],[],"",[],[],{"id":238,"title":239,"description":240,"type":241,"actorIds":242,"entryPoints":245,"languages":248,"intent":234,"supportingSections":249,"references":250},"shortener-web","Shortener web application","The supported browser Interface for both sides of a short link: the signed-in\nOwner who creates and manages links, and the Visitor who follows a short\naddress without an account.","web",[243,244],"owner","visitor",[246],{"type":241,"path":247},"\u002F",[],[],[],[252,264],{"id":253,"title":254,"description":255,"actorIds":256,"interfaceIds":257,"accessMode":258,"entryPoints":259,"intent":234,"supportingSections":262,"references":263},"shortener-web::dashboard","Dashboard","The signed-in context in which an Owner creates, finds, edits, disables and\nreads the analytics of their links, and issues and revokes the API keys their\ntools use. Everything here belongs to the signed-in Owner.",[243],[238],"authenticated",[260],{"type":238,"path":261},"\u002Flinks",[],[],{"id":265,"title":266,"description":267,"actorIds":268,"interfaceIds":269,"accessMode":32,"entryPoints":270,"intent":234,"supportingSections":273,"references":274},"shortener-web::redirect","Redirect","What a Visitor meets when they follow a short address: the destination, or a\nneutral statement that the link is unavailable. It requires no account and\nreveals nothing else about the link or its Owner.",[244],[238],[271],{"type":238,"path":272},"\u002F:slug",[],[],[276,301,343,366],{"id":277,"title":278,"description":279,"capabilityIds":280,"entities":283,"capabilityScenarioIds":292,"journeyScenarioIds":295,"entryPoints":296,"intent":234,"supportingSections":299,"references":300},"shortener-web::dashboard::api-keys","API keys","Lists the Owner's API keys by name, with when each was created and last used.\nThe Owner creates a key here, sees its secret once at creation, and revokes a\nkey a tool should no longer use once they confirm.",[281,282],"create-api-key","revoke-api-key",[284],{"entityId":285,"shows":286,"collects":291},"api-key",[287,288,289,290],"Created at","Last used at","Name","Secret",[289],[293,294],"create-an-api-key","revoke-an-api-key",[],[297],{"type":238,"path":298},"\u002Fsettings\u002Fapi-keys",[],[],{"id":302,"title":303,"description":304,"capabilityIds":305,"entities":311,"capabilityScenarioIds":327,"journeyScenarioIds":337,"entryPoints":338,"intent":234,"supportingSections":341,"references":342},"shortener-web::dashboard::link-detail","Link detail","One of the Owner's links: its short address, destination, state, expiry and\nwhen it was created, and how it has been followed — clicks over time, and the\nreferring sites, countries and devices they came from. Here the Owner changes\nthe destination or the expiry, and disables or enables the link.",[306,307,308,309,310],"disable-link","edit-link","enable-link","search-links","view-link-analytics",[312,320],{"entityId":313,"shows":314,"collects":319},"click",[315,316,317,318],"Clicked at","Country","Device","Referring site",[],{"entityId":321,"shows":322,"collects":326},"link",[287,323,324,325],"Destination","Expires at","Slug",[323,324],[328,329,330,331,332,333,334,335,336],"change-a-links-destination","disable-a-link","enable-a-disabled-link","enable-a-link-whose-expiry-has-passed","find-a-link-by-slug-or-destination","give-an-expired-link-a-new-expiry","narrow-analytics-to-a-period","see-how-a-link-has-been-followed","set-a-links-expiry",[],[339],{"type":238,"path":340},"\u002Flinks\u002F:linkId",[],[],{"id":344,"title":345,"description":346,"capabilityIds":347,"entities":350,"capabilityScenarioIds":357,"journeyScenarioIds":361,"entryPoints":362,"intent":234,"supportingSections":364,"references":365},"shortener-web::dashboard::links","Links","Lists the Owner's links, newest first, with each one's short address,\ndestination, state, expiry and how many times it has been followed. The Owner\nfinds a link here by its slug or destination, opens one, or starts a new one.",[348,307,349,309,310],"create-link","expire-link",[351,354],{"entityId":313,"shows":352,"collects":353},[315],[],{"entityId":321,"shows":355,"collects":356},[287,323,324,325],[],[328,358,359,360,332,333,335],"create-a-link-with-a-custom-slug","create-a-link-with-a-generated-slug","expire-a-link-when-its-expiry-passes",[],[363],{"type":238,"path":261},[],[],{"id":367,"title":368,"description":369,"capabilityIds":370,"entities":371,"capabilityScenarioIds":375,"journeyScenarioIds":378,"entryPoints":379,"intent":234,"supportingSections":382,"references":383},"shortener-web::dashboard::new-link","New link","Takes an Owner through creating a link: the destination it leads to, a slug of\ntheir own or one the Product generates, and an optional expiry. A refused slug\nor destination is explained here, with everything entered kept to correct, and\na created link's short address is shown here, ready to copy.",[348],[372],{"entityId":321,"shows":373,"collects":374},[323,324,325],[323,324,325],[358,359,376,377],"reject-a-destination-that-cannot-be-shortened","reject-a-slug-already-in-use",[],[380],{"type":238,"path":381},"\u002Flinks\u002Fnew",[],[],[385,391],{"id":386,"name":278,"description":387,"boundary":388,"colorSlot":48,"intent":234,"supportingSections":389,"references":390},"api-keys","The keys an Owner issues so their own tools can create links through the API,\nand the revocation that stops a tool from using one.","Owns which API keys exist, their names and secrets, and when each was last\nused. It does not own the links a tool creates with a key: those are the\nOwner's links like any other.",[],[],{"id":392,"name":345,"description":393,"boundary":394,"colorSlot":36,"intent":234,"supportingSections":395,"references":396},"links","The Owner's links: creating them, changing where they lead, disabling them,\nletting them expire, finding them again, and reading how they were followed.","Owns links, their slugs, destinations, expiry and state, and the clicks they\nreceive. It does not own the API keys a tool creates links with, or the\nredirect a Visitor meets when following a short address.",[],[],[398,409,429,445,473,485],{"id":231,"title":399,"description":400,"kind":401,"acts":402,"singleton":403,"informationKept":404,"relations":405,"states":406,"intent":234,"supportingSections":407,"references":408},"API client","A program an Owner runs — a script, a publishing tool, a form backend — that\ncreates links through the API by presenting one of that Owner's API keys. It\ncreates links and does nothing else.","system","external",false,[],[],[],[],[],{"id":285,"title":410,"description":411,"domainId":386,"kind":412,"acts":412,"singleton":403,"informationKept":413,"relations":422,"states":426,"intent":234,"supportingSections":427,"references":428},"API key","A credential an Owner issues so one of their tools can create links in their\naccount. A revoked key no longer exists, and a request presenting it is\nrefused.",null,[414,416,418,420],{"name":289,"description":415},"what the Owner calls it, usually the tool it is for",{"name":290,"description":417},"the value the API client presents with each request",{"name":287,"description":419},"when the Owner created it",{"name":288,"description":421},"when an API client last presented it, if one has",[423],{"entityId":231,"verb":424,"cardinality":425},"identifies","one-to-one",[],[],[],{"id":313,"title":430,"description":431,"domainId":392,"kind":412,"acts":412,"singleton":403,"informationKept":432,"relations":441,"states":442,"intent":234,"supportingSections":443,"references":444},"Click","One follow of an active short address, kept so its Owner can see how the link\ntravels. A click describes where the follow came from, never who made it.",[433,435,437,439],{"name":315,"description":434},"when the short address was followed",{"name":318,"description":436},"the site the Visitor came from, when their browser said so",{"name":316,"description":438},"the country the follow came from",{"name":317,"description":440},"the kind of device it came from: desktop, phone or tablet",[],[],[],[],{"id":321,"title":446,"description":447,"domainId":392,"kind":412,"acts":412,"singleton":403,"informationKept":448,"relations":457,"states":461,"intent":234,"supportingSections":471,"references":472},"Link","A short address and the destination it sends Visitors to. The short address\nis the Product's short domain followed by the link's slug.",[449,451,453,455],{"name":325,"description":450},"the short part of the address that names this link, generated by the Product or chosen by the Owner",{"name":323,"description":452},"the full web address a Visitor is sent to",{"name":324,"description":454},"when the link stops redirecting on its own, if the Owner set an expiry",{"name":287,"description":456},"when the link was created",[458],{"entityId":313,"verb":459,"cardinality":460},"receives","one-to-many",[462,465,468],{"name":463,"content":464},"Active","Following the short address sends a Visitor to the destination and records a\nclick.",{"name":466,"content":467},"Disabled","Switched off by its Owner. The short address shows that the link is\nunavailable, and nothing about the link is lost until the Owner enables it\nagain.",{"name":469,"content":470},"Expired","Its expiry passed while it was active. The short address shows that the link\nis unavailable until the Owner gives it a later expiry or removes it.",[],[],{"id":243,"title":474,"description":475,"kind":476,"acts":402,"singleton":403,"informationKept":477,"relations":478,"states":482,"intent":234,"supportingSections":483,"references":484},"Owner","A person with an account who creates short links, manages them and reads how\nthey are followed. Every link and every API key belongs to exactly one Owner.","person",[],[479,481],{"entityId":321,"verb":480,"cardinality":460},"owns",{"entityId":285,"verb":480,"cardinality":460},[],[],[],{"id":244,"title":486,"description":487,"kind":476,"acts":402,"singleton":403,"informationKept":488,"relations":489,"states":490,"intent":234,"supportingSections":491,"references":492},"Visitor","Someone who follows a short address, without an account. A Visitor is sent on\nto the link's destination and learns nothing else about the link or its Owner.",[],[],[],[],[],[494,502,511,519,527,535,543,552,560,568],{"id":281,"title":495,"description":496,"domainId":386,"availability":497,"intent":499,"supportingSections":500,"references":501},"API key creation","Issues a named API key in the Owner's account and shows its secret once, so\nthe Owner can give it to the tool that will create links with it.",[498],{"placeId":253},"Let an Owner connect a tool of their own to the Product deliberately, one key\nper tool, so each can be cut off without affecting the others.",[],[],{"id":348,"title":503,"description":504,"domainId":392,"availability":505,"intent":508,"supportingSections":509,"references":510},"Link creation","Creates an active link from a destination, with a slug the Product generates\nor one the Owner chooses and an optional expiry — on the web, or through the\nAPI by a tool holding one of the Owner's API keys.",[506,507],{"placeId":227},{"placeId":253},"Make a short, unique, dependable address for any web destination in one step,\nwhether a person or their tool asks for it.",[],[],{"id":306,"title":512,"description":513,"domainId":392,"availability":514,"intent":516,"supportingSections":517,"references":518},"Link disabling","Switches one of the Owner's links off, so its short address stops redirecting\nwhile the link, its slug and its clicks are kept.",[515],{"placeId":253},"Give an Owner an immediate way to stop a short address they no longer want\nfollowed, without losing the link, its slug or its history.",[],[],{"id":307,"title":520,"description":521,"domainId":392,"availability":522,"intent":524,"supportingSections":525,"references":526},"Link editing","Changes where one of the Owner's links leads and when it expires, keeping its\nslug and every click it has received.",[523],{"placeId":253},"Let an Owner correct or move a short address they have already handed out,\nwithout handing out a new one.",[],[],{"id":308,"title":528,"description":529,"domainId":392,"availability":530,"intent":532,"supportingSections":533,"references":534},"Link enabling","Switches one of the Owner's disabled links back on, so the same short address\nredirects again unless its expiry has passed meanwhile.",[531],{"placeId":253},"Make disabling a link reversible: an Owner who paused a short address can bring\nit back without handing out a new one.",[],[],{"id":349,"title":536,"description":537,"domainId":392,"availability":538,"intent":540,"supportingSections":541,"references":542},"Link expiry","Expires an active link on the Product's own schedule once the expiry its Owner\nset has passed.",[539],{"placeId":253},"Let a link with a known end stop working on time without anyone remembering to\nswitch it off.",[],[],{"id":544,"title":545,"description":546,"availability":547,"intent":549,"supportingSections":550,"references":551},"follow-link","Link redirection","Sends a Visitor who follows a short address on to the link's destination and\nrecords the click, or tells them the link is unavailable.",[548],{"placeId":265},"Make a short address as dependable as the long one it stands for while it is\nactive, and reveal nothing about the link once it is not.",[],[],{"id":282,"title":553,"description":554,"domainId":386,"availability":555,"intent":557,"supportingSections":558,"references":559},"API key revocation","Revokes one of the Owner's API keys for good, once the Owner confirms, so any\ntool still presenting it is refused.",[556],{"placeId":253},"Let an Owner cut off a tool they no longer trust or use, at once, without\ntouching the links it already created.",[],[],{"id":309,"title":561,"description":562,"domainId":392,"availability":563,"intent":565,"supportingSections":566,"references":567},"Link search","Finds the Owner's links by any part of their slug or destination, whatever\nstate they are in.",[564],{"placeId":253},"Let an Owner get back to any link they made from whatever they remember about\nit.",[],[],{"id":310,"title":569,"description":570,"domainId":392,"availability":571,"intent":573,"supportingSections":574,"references":575},"Link analytics","Presents how one of the Owner's links has been followed: how many clicks, when,\nand the referring sites, countries and devices they came from.",[572],{"placeId":253},"Show an Owner where a short address travelled and whether it worked, without\nthe Product learning who followed it.",[],[],[577,629,691,737,779,821,855,888,920,953,992,1032,1070,1101,1127,1160,1187,1217,1262,1302],{"id":328,"capabilityId":307,"title":578,"kindId":218,"actorIds":579,"routes":580,"steps":583,"trigger":622,"decisionPoints":623,"outcome":624,"edgeCases":625,"intent":234,"supportingSections":627,"references":628},"Change a link's destination",[243],[581],{"id":241,"name":582},"Web",[584,593,598,604,612],{"text":585,"kind":586,"actorId":243,"capabilityId":307,"entities":587,"unattended":403,"contexts":591},"The Owner opens a link from their links","actor",[588],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":590,"with":412},"reads",[323,325],[592],{"routeId":241,"placeId":344},{"text":594,"kind":586,"actorId":243,"capabilityId":307,"entities":595,"unattended":403,"contexts":596},"The Owner enters a new destination",[],[597],{"routeId":241,"placeId":302},{"text":599,"kind":600,"actorId":243,"capabilityId":307,"entities":601,"unattended":403,"contexts":602},"The Product checks that the new destination is a web address outside the shortener","product",[],[603],{"routeId":241,"placeId":302},{"text":605,"kind":586,"actorId":243,"capabilityId":307,"entities":606,"unattended":403,"contexts":610},"The Owner saves the change",[607],{"entityId":321,"as":412,"effect":608,"from":412,"to":412,"facts":609,"with":412},"changes",[323],[611],{"routeId":241,"placeId":302},{"text":613,"kind":614,"actorId":243,"capabilityId":307,"entities":615,"unattended":403,"contexts":620},"The link keeps its slug and the clicks it has already received","condition",[616,618],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":617,"with":412},[325],{"entityId":313,"as":412,"effect":589,"from":412,"to":412,"facts":619,"with":412},[],[621],{"routeId":241,"placeId":302},"The address a short link leads to has moved, or the Owner wants it to lead\nsomewhere else.",[],"Following the same short address now sends Visitors to the new destination,\nand the link's earlier clicks are still in its analytics.",[626],"The new destination is not a web address or is a short address of this Product → nothing is saved, and the Product explains why with the entry kept.",[],[],{"id":630,"capabilityId":348,"title":631,"kindId":218,"actorIds":632,"routes":633,"steps":636,"trigger":675,"decisionPoints":676,"outcome":686,"edgeCases":687,"intent":234,"supportingSections":689,"references":690},"create-a-link-through-the-api","Create a link through the API",[231],[634],{"id":172,"name":635},"API",[637,644,651,658,668],{"text":638,"kind":586,"actorId":231,"capabilityId":348,"entities":639,"unattended":403,"contexts":642},"The API client sends a destination, optionally a slug and an expiry, with an API key",[640],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":641,"with":412},[],[643],{"routeId":172,"placeId":227},{"text":645,"kind":600,"actorId":231,"capabilityId":348,"entities":646,"unattended":403,"contexts":649},"The Product recognizes the API key and records that it was just used",[647],{"entityId":285,"as":412,"effect":608,"from":412,"to":412,"facts":648,"with":412},[288],[650],{"routeId":172,"placeId":227},{"text":652,"kind":600,"actorId":231,"capabilityId":348,"entities":653,"unattended":403,"contexts":656},"The Product checks the destination and, when a slug was sent, that no link has it",[654],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":655,"with":412},[325],[657],{"routeId":172,"placeId":227},{"text":659,"kind":600,"actorId":231,"capabilityId":348,"entities":660,"unattended":403,"contexts":666},"The Product creates an active link in the account the API key belongs to",[661,664],{"entityId":321,"as":412,"effect":662,"from":412,"to":463,"facts":663,"with":412},"creates",[287,323,324,325],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":665,"with":412},[],[667],{"routeId":172,"placeId":227},{"text":669,"kind":600,"actorId":231,"capabilityId":348,"entities":670,"unattended":403,"contexts":673},"The Product answers with the new link's short address",[671],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":672,"with":412},[325],[674],{"routeId":172,"placeId":227},"A tool the Owner runs needs a short address for a destination.",[677],{"title":325,"question":678,"branches":679},"Did the request carry a slug?",[680,683],{"condition":681,"outcome":682},"A slug was sent and no link has it","the link uses that slug.",{"condition":684,"outcome":685},"No slug was sent","the Product generates one no other link has ever had.","The tool has the short address of an active link that belongs to the Owner of\nthe API key, listed among the Owner's links like any link created on the web.",[688],"The slug sent is taken, or the destination cannot be shortened → no link is created and the answer says why.",[],[],{"id":358,"capabilityId":348,"title":692,"kindId":218,"actorIds":693,"routes":694,"steps":696,"trigger":730,"decisionPoints":731,"outcome":732,"edgeCases":733,"intent":234,"supportingSections":735,"references":736},"Create a link with a custom slug",[243],[695],{"id":241,"name":582},[697,704,709,716,723],{"text":698,"kind":586,"actorId":243,"capabilityId":348,"entities":699,"unattended":403,"contexts":702},"The Owner starts a new link",[700],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":701,"with":412},[],[703],{"routeId":241,"placeId":344},{"text":705,"kind":586,"actorId":243,"capabilityId":348,"entities":706,"unattended":403,"contexts":707},"The Owner enters the destination and a slug of their own, and optionally sets an expiry",[],[708],{"routeId":241,"placeId":367},{"text":710,"kind":600,"actorId":243,"capabilityId":348,"entities":711,"unattended":403,"contexts":714},"The Product checks that the destination is a web address outside the shortener and that no link has the slug",[712],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":713,"with":412},[325],[715],{"routeId":241,"placeId":367},{"text":717,"kind":600,"actorId":243,"capabilityId":348,"entities":718,"unattended":403,"contexts":721},"The Product creates an active link with the chosen slug",[719],{"entityId":321,"as":412,"effect":662,"from":412,"to":463,"facts":720,"with":412},[287,323,324,325],[722],{"routeId":241,"placeId":367},{"text":724,"kind":600,"actorId":243,"capabilityId":348,"entities":725,"unattended":403,"contexts":728},"The Product shows the new link's short address in place, ready to copy and hand out",[726],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":727,"with":412},[323,324,325],[729],{"routeId":241,"placeId":367},"The Owner wants a short address that people can read, remember or type.",[],"The Owner has an active link whose short address ends in the slug they chose,\nand is looking at that address.",[734],"The slug uses characters a short address cannot carry → the link is not created, and the Product says which characters are allowed, keeping everything entered.",[],[],{"id":359,"capabilityId":348,"title":738,"kindId":218,"actorIds":739,"routes":740,"steps":742,"trigger":772,"decisionPoints":773,"outcome":774,"edgeCases":775,"intent":234,"supportingSections":777,"references":778},"Create a link with a generated slug",[243],[741],{"id":241,"name":582},[743,749,754,759,766],{"text":698,"kind":586,"actorId":243,"capabilityId":348,"entities":744,"unattended":403,"contexts":747},[745],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":746,"with":412},[],[748],{"routeId":241,"placeId":344},{"text":750,"kind":586,"actorId":243,"capabilityId":348,"entities":751,"unattended":403,"contexts":752},"The Owner enters the destination, leaves the slug for the Product to choose, and optionally sets an expiry",[],[753],{"routeId":241,"placeId":367},{"text":755,"kind":600,"actorId":243,"capabilityId":348,"entities":756,"unattended":403,"contexts":757},"The Product checks that the destination is a web address outside the shortener",[],[758],{"routeId":241,"placeId":367},{"text":760,"kind":600,"actorId":243,"capabilityId":348,"entities":761,"unattended":403,"contexts":764},"The Product creates an active link with a slug no other link has ever had",[762],{"entityId":321,"as":412,"effect":662,"from":412,"to":463,"facts":763,"with":412},[287,323,324,325],[765],{"routeId":241,"placeId":367},{"text":724,"kind":600,"actorId":243,"capabilityId":348,"entities":767,"unattended":403,"contexts":770},[768],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":769,"with":412},[323,324,325],[771],{"routeId":241,"placeId":367},"The Owner has a long address they want to hand out and has no preference for\nthe slug.",[],"The Owner has an active link with a short, unique generated slug that sends\nVisitors to the destination, and is looking at its short address.",[776],"The Owner sets an expiry that has already passed → the link is not created, and the Product asks for a later one with everything entered kept.",[],[],{"id":293,"capabilityId":281,"title":780,"kindId":218,"actorIds":781,"routes":782,"steps":784,"trigger":813,"decisionPoints":814,"outcome":815,"edgeCases":816,"intent":234,"supportingSections":819,"references":820},"Create an API key",[243],[783],{"id":241,"name":582},[785,792,799,806],{"text":786,"kind":586,"actorId":243,"capabilityId":281,"entities":787,"unattended":403,"contexts":790},"The Owner names a new API key after the tool it is for",[788],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":789,"with":412},[],[791],{"routeId":241,"placeId":277},{"text":793,"kind":600,"actorId":243,"capabilityId":281,"entities":794,"unattended":403,"contexts":797},"The Product creates the API key with a secret of its own making",[795],{"entityId":285,"as":412,"effect":662,"from":412,"to":412,"facts":796,"with":412},[287,288,289,290],[798],{"routeId":241,"placeId":277},{"text":800,"kind":600,"actorId":243,"capabilityId":281,"entities":801,"unattended":403,"contexts":804},"The Product shows the secret once, ready to copy, and says it will not be shown again",[802],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":803,"with":412},[289,290],[805],{"routeId":241,"placeId":277},{"text":807,"kind":614,"actorId":412,"capabilityId":281,"entities":808,"unattended":403,"contexts":811},"The API key is listed by name, never again with its secret",[809],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":810,"with":412},[287,288,289],[812],{"routeId":241,"placeId":277},"The Owner wants a tool of their own to create links in their account.",[],"The Owner holds the secret of a new API key, named for its tool, that the\ntool can present to create links; the Product will not show that secret again.",[817,818],"The Owner leaves without copying the secret → it cannot be shown again; the Owner revokes the key and creates another.","The Owner gives no name → no key is created, and the Product asks for one.",[],[],{"id":329,"capabilityId":306,"title":822,"kindId":218,"actorIds":823,"routes":824,"steps":826,"trigger":848,"decisionPoints":849,"outcome":850,"edgeCases":851,"intent":234,"supportingSections":853,"references":854},"Disable a link",[243],[825],{"id":241,"name":582},[827,834,841],{"text":828,"kind":586,"actorId":243,"capabilityId":306,"entities":829,"unattended":403,"contexts":832},"The Owner chooses to disable an active link",[830],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":831,"with":412},[325],[833],{"routeId":241,"placeId":302},{"text":835,"kind":600,"actorId":243,"capabilityId":306,"entities":836,"unattended":403,"contexts":839},"The Product explains that the short address will stop redirecting and say the link is unavailable",[837],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":838,"with":412},[],[840],{"routeId":241,"placeId":302},{"text":842,"kind":586,"actorId":243,"capabilityId":306,"entities":843,"unattended":403,"contexts":846},"The Owner confirms",[844],{"entityId":321,"as":412,"effect":608,"from":463,"to":466,"facts":845,"with":412},[],[847],{"routeId":241,"placeId":302},"The Owner no longer wants a short address they handed out to lead anywhere.",[],"The link is disabled: its short address shows that the link is unavailable,\nand its slug, destination and clicks are kept.",[852],"The Owner declines to confirm → the link stays active and nothing changes.",[],[],{"id":330,"capabilityId":308,"title":856,"kindId":218,"actorIds":857,"routes":858,"steps":860,"trigger":882,"decisionPoints":883,"outcome":884,"edgeCases":885,"intent":234,"supportingSections":886,"references":887},"Enable a disabled link",[243],[859],{"id":241,"name":582},[861,868,875],{"text":862,"kind":586,"actorId":243,"capabilityId":308,"entities":863,"unattended":403,"contexts":866},"The Owner chooses to enable a disabled link",[864],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":865,"with":412},[324,325],[867],{"routeId":241,"placeId":302},{"text":869,"kind":614,"actorId":412,"capabilityId":308,"entities":870,"unattended":403,"contexts":873},"The link has no expiry, or its expiry is still to come",[871],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":872,"with":412},[324],[874],{"routeId":241,"placeId":302},{"text":876,"kind":600,"actorId":243,"capabilityId":308,"entities":877,"unattended":403,"contexts":880},"The Product makes the link active again",[878],{"entityId":321,"as":412,"effect":608,"from":466,"to":463,"facts":879,"with":412},[],[881],{"routeId":241,"placeId":302},"The Owner wants a short address they disabled to work again.",[],"The same short address sends Visitors to the link's destination again.",[],[],[],{"id":331,"capabilityId":308,"title":889,"kindId":214,"actorIds":890,"routes":891,"steps":893,"trigger":914,"decisionPoints":915,"outcome":916,"edgeCases":917,"intent":234,"supportingSections":918,"references":919},"Enable a link whose expiry has passed",[243],[892],{"id":241,"name":582},[894,900,907],{"text":862,"kind":586,"actorId":243,"capabilityId":308,"entities":895,"unattended":403,"contexts":898},[896],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":897,"with":412},[324,325],[899],{"routeId":241,"placeId":302},{"text":901,"kind":614,"actorId":412,"capabilityId":308,"entities":902,"unattended":403,"contexts":905},"The link's expiry passed while it was disabled",[903],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":904,"with":412},[324],[906],{"routeId":241,"placeId":302},{"text":908,"kind":600,"actorId":243,"capabilityId":308,"entities":909,"unattended":403,"contexts":912},"The Product marks the link expired rather than active and says a later expiry would make it work again",[910],{"entityId":321,"as":412,"effect":608,"from":466,"to":469,"facts":911,"with":412},[],[913],{"routeId":241,"placeId":302},"The Owner enables a disabled link after the expiry it was given has passed.",[],"The link is no longer disabled but expired, its short address still shows\nthat it is unavailable, and the Owner knows a later expiry would bring it back.",[],[],[],{"id":360,"capabilityId":349,"title":921,"kindId":218,"actorIds":922,"routes":923,"steps":925,"trigger":946,"decisionPoints":947,"outcome":948,"edgeCases":949,"intent":234,"supportingSections":951,"references":952},"Expire a link when its expiry passes",[],[924],{"id":241,"name":582},[926,933,939],{"text":927,"kind":614,"actorId":412,"capabilityId":349,"entities":928,"unattended":931,"contexts":932},"The expiry of an active link passes",[929],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":930,"with":412},[324],true,[],{"text":934,"kind":600,"actorId":412,"capabilityId":349,"entities":935,"unattended":403,"contexts":938},"The Product expires the link",[936],{"entityId":321,"as":412,"effect":608,"from":463,"to":469,"facts":937,"with":412},[],[],{"text":940,"kind":614,"actorId":412,"capabilityId":349,"entities":941,"unattended":403,"contexts":944},"The link appears as expired in the list of links",[942],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":943,"with":412},[324,325],[945],{"routeId":241,"placeId":344},"The expiry an Owner set on an active link passes, with nobody present.",[],"The link is expired: its short address shows that the link is unavailable, and\nthe Owner sees it marked expired among their links.",[950],"The link is disabled when its expiry passes → it stays disabled; enabling it later finds it expired.",[],[],{"id":332,"capabilityId":309,"title":954,"kindId":218,"actorIds":955,"routes":956,"steps":958,"trigger":985,"decisionPoints":986,"outcome":987,"edgeCases":988,"intent":234,"supportingSections":990,"references":991},"Find a link by slug or destination",[243],[957],{"id":241,"name":582},[959,964,971,978],{"text":960,"kind":586,"actorId":243,"capabilityId":309,"entities":961,"unattended":403,"contexts":962},"The Owner enters part of a slug or a destination",[],[963],{"routeId":241,"placeId":344},{"text":965,"kind":600,"actorId":243,"capabilityId":309,"entities":966,"unattended":403,"contexts":969},"The Product lists the Owner's links whose slug or destination contains it, active, disabled and expired alike, each marked with its state",[967],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":968,"with":412},[287,323,324,325],[970],{"routeId":241,"placeId":344},{"text":972,"kind":586,"actorId":243,"capabilityId":309,"entities":973,"unattended":403,"contexts":976},"The Owner opens one of the links found",[974],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":975,"with":412},[323,325],[977],{"routeId":241,"placeId":344},{"text":979,"kind":600,"actorId":243,"capabilityId":309,"entities":980,"unattended":403,"contexts":983},"The Product shows that link in full",[981],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":982,"with":412},[287,323,324,325],[984],{"routeId":241,"placeId":302},"The Owner wants a link they made earlier and remembers part of its short\naddress or of where it leads.",[],"The Owner is looking at the link they wanted, found from what they remembered,\nwith nothing about any link changed.",[989],"Nothing matches → the Product says no link matches, and the entry stays available to change.",[],[],{"id":993,"capabilityId":544,"title":994,"kindId":214,"actorIds":995,"routes":996,"steps":998,"trigger":1025,"decisionPoints":1026,"outcome":1027,"edgeCases":1028,"intent":234,"supportingSections":1030,"references":1031},"follow-a-link-that-no-longer-redirects","Follow a link that no longer redirects",[244],[997],{"id":241,"name":582},[999,1004,1011,1018],{"text":1000,"kind":586,"actorId":244,"capabilityId":544,"entities":1001,"unattended":403,"contexts":1002},"The Visitor follows a short address",[],[1003],{"routeId":241,"placeId":265},{"text":1005,"kind":614,"actorId":412,"capabilityId":544,"entities":1006,"unattended":403,"contexts":1009},"The link with that slug is disabled or has expired",[1007],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1008,"with":412},[325],[1010],{"routeId":241,"placeId":265},{"text":1012,"kind":600,"actorId":244,"capabilityId":544,"entities":1013,"unattended":403,"contexts":1016},"The Product shows that the link is unavailable, without revealing where it led or whose it is",[1014],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1015,"with":412},[],[1017],{"routeId":241,"placeId":265},{"text":1019,"kind":614,"actorId":412,"capabilityId":544,"entities":1020,"unattended":403,"contexts":1023},"Nobody is sent on, and the link's analytics stay as they were",[1021],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1022,"with":412},[],[1024],{"routeId":241,"placeId":265},"A Visitor opens a short address whose link its Owner has disabled or that has\nexpired.",[],"The Visitor is told the link is unavailable and is not sent anywhere; nothing\nabout the link is revealed and its analytics are unchanged.",[1029],"No link has the slug in the address → the Visitor sees the same unavailable statement, so a mistyped address and a switched-off link look alike.",[],[],{"id":1033,"capabilityId":544,"title":1034,"kindId":218,"actorIds":1035,"routes":1036,"steps":1038,"trigger":1064,"decisionPoints":1065,"outcome":1066,"edgeCases":1067,"intent":234,"supportingSections":1068,"references":1069},"follow-an-active-link","Follow an active link",[244],[1037],{"id":241,"name":582},[1039,1043,1050,1057],{"text":1000,"kind":586,"actorId":244,"capabilityId":544,"entities":1040,"unattended":403,"contexts":1041},[],[1042],{"routeId":241,"placeId":265},{"text":1044,"kind":600,"actorId":244,"capabilityId":544,"entities":1045,"unattended":403,"contexts":1048},"The Product finds the active link with that slug",[1046],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1047,"with":412},[325],[1049],{"routeId":241,"placeId":265},{"text":1051,"kind":600,"actorId":244,"capabilityId":544,"entities":1052,"unattended":403,"contexts":1055},"The Product records a click with when it happened and the referring site, country and device it came from",[1053],{"entityId":313,"as":412,"effect":662,"from":412,"to":412,"facts":1054,"with":412},[315,316,317,318],[1056],{"routeId":241,"placeId":265},{"text":1058,"kind":600,"actorId":244,"capabilityId":544,"entities":1059,"unattended":403,"contexts":1062},"The Product sends the Visitor on to the link's destination",[1060],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1061,"with":412},[323],[1063],{"routeId":241,"placeId":265},"A Visitor opens a short address from a post, a message, a printed page or\nanywhere else it was handed out.",[],"The Visitor arrives at the destination, and the link's Owner can see one more\nclick in its analytics.",[],[],[],{"id":333,"capabilityId":307,"title":1071,"kindId":214,"actorIds":1072,"routes":1073,"steps":1075,"trigger":1095,"decisionPoints":1096,"outcome":1097,"edgeCases":1098,"intent":234,"supportingSections":1099,"references":1100},"Give an expired link a new expiry",[243],[1074],{"id":241,"name":582},[1076,1083,1088],{"text":1077,"kind":586,"actorId":243,"capabilityId":307,"entities":1078,"unattended":403,"contexts":1081},"The Owner opens a link that has expired",[1079],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1080,"with":412},[324,325],[1082],{"routeId":241,"placeId":344},{"text":1084,"kind":586,"actorId":243,"capabilityId":307,"entities":1085,"unattended":403,"contexts":1086},"The Owner sets a later expiry, or removes the expiry",[],[1087],{"routeId":241,"placeId":302},{"text":1089,"kind":586,"actorId":243,"capabilityId":307,"entities":1090,"unattended":403,"contexts":1093},"The Owner saves, and the link is active again",[1091],{"entityId":321,"as":412,"effect":608,"from":469,"to":463,"facts":1092,"with":412},[324],[1094],{"routeId":241,"placeId":302},"The Owner wants a link that has expired to work again.",[],"The same short address sends Visitors to the destination again until the new\nexpiry, or indefinitely when the expiry was removed.",[],[],[],{"id":334,"capabilityId":310,"title":1102,"kindId":218,"actorIds":1103,"routes":1104,"steps":1106,"trigger":1121,"decisionPoints":1122,"outcome":1123,"edgeCases":1124,"intent":234,"supportingSections":1125,"references":1126},"Narrow analytics to a period",[243],[1105],{"id":241,"name":582},[1107,1114],{"text":1108,"kind":586,"actorId":243,"capabilityId":310,"entities":1109,"unattended":403,"contexts":1112},"The Owner chooses a period on a link's analytics",[1110],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1111,"with":412},[325],[1113],{"routeId":241,"placeId":302},{"text":1115,"kind":600,"actorId":243,"capabilityId":310,"entities":1116,"unattended":403,"contexts":1119},"The Product presents only the clicks from that period, over time and by referring site, country and device",[1117],{"entityId":313,"as":412,"effect":589,"from":412,"to":412,"facts":1118,"with":412},[315,316,317,318],[1120],{"routeId":241,"placeId":302},"The Owner wants to see how a link did during a particular stretch of time,\nsuch as the week of a campaign.",[],"The Owner sees the link's clicks from the chosen period only, and every click\noutside it is still kept.",[],[],[],{"id":1128,"capabilityId":348,"title":1129,"kindId":222,"actorIds":1130,"routes":1131,"steps":1133,"trigger":1153,"decisionPoints":1154,"outcome":1155,"edgeCases":1156,"intent":234,"supportingSections":1158,"references":1159},"refuse-a-request-without-a-valid-api-key","Refuse a request without a valid API key",[231],[1132],{"id":172,"name":635},[1134,1141,1148],{"text":1135,"kind":586,"actorId":231,"capabilityId":348,"entities":1136,"unattended":403,"contexts":1139},"The API client sends a destination with an API key that was revoked or never issued",[1137],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":1138,"with":412},[],[1140],{"routeId":172,"placeId":227},{"text":1142,"kind":614,"actorId":412,"capabilityId":348,"entities":1143,"unattended":403,"contexts":1146},"No existing API key matches what was presented",[1144],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":1145,"with":412},[],[1147],{"routeId":172,"placeId":227},{"text":1149,"kind":600,"actorId":231,"capabilityId":348,"entities":1150,"unattended":403,"contexts":1151},"The Product refuses the request without creating anything",[],[1152],{"routeId":172,"placeId":227},"A tool asks for a link presenting a key the Product does not recognize,\nincluding one its Owner has revoked.",[],"No link is created, the answer says the key is not accepted, and nothing\nabout any account is revealed.",[1157],"The request carries no key at all → it is refused the same way.",[],[],{"id":376,"capabilityId":348,"title":1161,"kindId":222,"actorIds":1162,"routes":1163,"steps":1165,"trigger":1181,"decisionPoints":1182,"outcome":1183,"edgeCases":1184,"intent":234,"supportingSections":1185,"references":1186},"Reject a destination that cannot be shortened",[243],[1164],{"id":241,"name":582},[1166,1171,1176],{"text":1167,"kind":586,"actorId":243,"capabilityId":348,"entities":1168,"unattended":403,"contexts":1169},"The Owner enters a destination that is not a web address, or is itself a short address of this Product",[],[1170],{"routeId":241,"placeId":367},{"text":1172,"kind":614,"actorId":412,"capabilityId":348,"entities":1173,"unattended":403,"contexts":1174},"The Product finds the destination cannot be shortened",[],[1175],{"routeId":241,"placeId":367},{"text":1177,"kind":600,"actorId":243,"capabilityId":348,"entities":1178,"unattended":403,"contexts":1179},"The Product explains why and keeps what was entered to correct",[],[1180],{"routeId":241,"placeId":367},"The Owner enters a destination that is not a web address or that points back\ninto the shortener.",[],"No link is created, the Owner knows why, and the destination they entered\nremains available to correct.",[],[],[],{"id":377,"capabilityId":348,"title":1188,"kindId":222,"actorIds":1189,"routes":1190,"steps":1192,"trigger":1210,"decisionPoints":1211,"outcome":1212,"edgeCases":1213,"intent":234,"supportingSections":1215,"references":1216},"Reject a slug already in use",[243],[1191],{"id":241,"name":582},[1193,1198,1205],{"text":1194,"kind":586,"actorId":243,"capabilityId":348,"entities":1195,"unattended":403,"contexts":1196},"The Owner enters a destination and a slug of their own",[],[1197],{"routeId":241,"placeId":367},{"text":1199,"kind":614,"actorId":412,"capabilityId":348,"entities":1200,"unattended":403,"contexts":1203},"The Product finds that a link already has that slug",[1201],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1202,"with":412},[325],[1204],{"routeId":241,"placeId":367},{"text":1206,"kind":600,"actorId":243,"capabilityId":348,"entities":1207,"unattended":403,"contexts":1208},"The Product says the slug is taken and keeps the destination and slug to change",[],[1209],{"routeId":241,"placeId":367},"The Owner chooses a slug that another link already has.",[],"No link is created, the existing link with that slug is untouched, and the\nOwner can pick another slug without entering the destination again.",[1214],"The slug belongs to a disabled or expired link, the Owner's own included → it is still taken.",[],[],{"id":294,"capabilityId":282,"title":1218,"kindId":218,"actorIds":1219,"routes":1220,"steps":1222,"trigger":1255,"decisionPoints":1256,"outcome":1257,"edgeCases":1258,"intent":234,"supportingSections":1260,"references":1261},"Revoke an API key",[243],[1221],{"id":241,"name":582},[1223,1230,1239,1246],{"text":1224,"kind":586,"actorId":243,"capabilityId":282,"entities":1225,"unattended":403,"contexts":1228},"The Owner chooses to revoke an API key",[1226],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":1227,"with":412},[288,289],[1229],{"routeId":241,"placeId":277},{"text":1231,"kind":600,"actorId":243,"capabilityId":282,"entities":1232,"unattended":403,"contexts":1237},"The Product warns that any tool using the API key will be refused from now on, and that links it created stay",[1233,1235],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":1234,"with":412},[],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1236,"with":412},[],[1238],{"routeId":241,"placeId":277},{"text":842,"kind":586,"actorId":243,"capabilityId":282,"entities":1240,"unattended":403,"contexts":1244},[1241],{"entityId":285,"as":412,"effect":1242,"from":412,"to":412,"facts":1243,"with":412},"removes",[],[1245],{"routeId":241,"placeId":277},{"text":1247,"kind":614,"actorId":243,"capabilityId":282,"entities":1248,"unattended":403,"contexts":1253},"Links created with the API key stay active and remain the Owner's",[1249,1251],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1250,"with":412},[],{"entityId":285,"as":412,"effect":589,"from":412,"to":412,"facts":1252,"with":412},[],[1254],{"routeId":241,"placeId":277},"The Owner no longer wants a tool to create links in their account, or fears\nits secret has leaked.",[],"The API key is gone: a tool presenting its secret is refused, and every link\ncreated with it is unchanged.",[1259],"The Owner declines to confirm → the API key stays and keeps working.",[],[],{"id":335,"capabilityId":310,"title":1263,"kindId":218,"actorIds":1264,"routes":1265,"steps":1267,"trigger":1294,"decisionPoints":1295,"outcome":1296,"edgeCases":1297,"intent":234,"supportingSections":1300,"references":1301},"See how a link has been followed",[243],[1266],{"id":241,"name":582},[1268,1276,1285],{"text":585,"kind":586,"actorId":243,"capabilityId":310,"entities":1269,"unattended":403,"contexts":1274},[1270,1272],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1271,"with":412},[323,325],{"entityId":313,"as":412,"effect":589,"from":412,"to":412,"facts":1273,"with":412},[315],[1275],{"routeId":241,"placeId":344},{"text":1277,"kind":600,"actorId":243,"capabilityId":310,"entities":1278,"unattended":403,"contexts":1283},"The Product presents the link's clicks over time, with the referring sites, countries and devices they came from",[1279,1281],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1280,"with":412},[325],{"entityId":313,"as":412,"effect":589,"from":412,"to":412,"facts":1282,"with":412},[315,316,317,318],[1284],{"routeId":241,"placeId":302},{"text":1286,"kind":614,"actorId":243,"capabilityId":310,"entities":1287,"unattended":403,"contexts":1292},"Reading the analytics changes nothing about the link or its clicks",[1288,1290],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1289,"with":412},[],{"entityId":313,"as":412,"effect":589,"from":412,"to":412,"facts":1291,"with":412},[],[1293],{"routeId":241,"placeId":302},"The Owner wants to know whether a link they handed out is being followed, and\nfrom where.",[],"The Owner sees the link's clicks since it was created, over time and by\nreferring site, country and device.",[1298,1299],"Nobody has followed the link yet → its analytics show no clicks rather than an error.","Clicks from before a change of destination → they stay in the link's analytics with the rest.",[],[],{"id":336,"capabilityId":307,"title":1303,"kindId":218,"actorIds":1304,"routes":1305,"steps":1307,"trigger":1327,"decisionPoints":1328,"outcome":1329,"edgeCases":1330,"intent":234,"supportingSections":1333,"references":1334},"Set a link's expiry",[243],[1306],{"id":241,"name":582},[1308,1315,1320],{"text":1309,"kind":586,"actorId":243,"capabilityId":307,"entities":1310,"unattended":403,"contexts":1313},"The Owner picks when an active link should stop redirecting",[1311],{"entityId":321,"as":412,"effect":589,"from":412,"to":412,"facts":1312,"with":412},[324],[1314],{"routeId":241,"placeId":302},{"text":1316,"kind":600,"actorId":243,"capabilityId":307,"entities":1317,"unattended":403,"contexts":1318},"The Product checks that the chosen time is still to come",[],[1319],{"routeId":241,"placeId":302},{"text":1321,"kind":586,"actorId":243,"capabilityId":307,"entities":1322,"unattended":403,"contexts":1325},"The Owner saves the expiry",[1323],{"entityId":321,"as":412,"effect":608,"from":412,"to":412,"facts":1324,"with":412},[324],[1326],{"routeId":241,"placeId":302},"The Owner wants a link to stop working on its own at a known time, such as the\nend of a campaign.",[],"The link stays active until the chosen time and then expires without the\nOwner doing anything more.",[1331,1332],"The Owner removes an existing expiry → the link stays active until they disable it.","The chosen time has already passed → nothing is saved, and the Product asks for a later one.",[],[],[],[],[1338,1355,1366,1390,1407,1424,1435,1447,1459,1480,1497,1514],{"id":1339,"title":1340,"statement":1341,"rationale":1342,"appliesTo":1343,"permits":1348,"intent":234,"supportingSections":1353,"references":1354},"a-click-is-recorded-only-when-a-visitor-follows-a-link","A click is recorded only when a Visitor follows a link","A click comes into being only when a Visitor follows an active short address.\nAn Owner cannot add clicks to a link, and an API client cannot record them.","A link's analytics are worth reading only if every click in them is a real\nfollow of its short address.",[1344],{"type":1345,"entityId":313,"effect":662,"from":412,"to":412,"facts":1346,"contexts":1347},"entity",[],[],[1349],{"actorIds":1350,"related":1351,"self":403,"when":1352,"unattended":403,"configuredByEntityId":412},[244],[],[],[],[],{"id":1356,"title":1357,"statement":1358,"rationale":1359,"appliesTo":1360,"permits":412,"intent":234,"supportingSections":1364,"references":1365},"a-destination-is-never-a-short-address","A destination is never a short address","A link's destination is a web address outside the shortener. A destination\nthat is itself one of the Product's short addresses is refused, on the web and\nthrough the API alike, whether the link is being created or changed.","A short address pointing at another short address hides the real destination\nfrom the Owner and can send Visitors round in a loop that never arrives.",[1361],{"type":1345,"entityId":321,"effect":412,"from":412,"to":412,"facts":1362,"contexts":1363},[323],[],[],[],{"id":1367,"title":1368,"statement":1369,"rationale":1370,"appliesTo":1371,"permits":1375,"intent":234,"supportingSections":1388,"references":1389},"a-link-is-created-by-its-owner-or-with-their-api-key","A link is created by its Owner or with their API key","A link comes into being only in an Owner's account: created by the Owner on the\nweb, or by an API client presenting one of that Owner's API keys. A link an\nAPI client creates belongs to the Owner of the key it presented.","Every short address needs an Owner who can change, disable and account for it.\nAn API client never holds links of its own.",[1372],{"type":1345,"entityId":321,"effect":662,"from":412,"to":412,"facts":1373,"contexts":1374},[],[],[1376,1381],{"actorIds":1377,"related":1378,"self":403,"when":1380,"unattended":403,"configuredByEntityId":412},[],[1379],{"verb":480,"entityId":243},[],{"actorIds":1382,"related":1383,"self":403,"when":1387,"unattended":403,"configuredByEntityId":412},[],[1384,1385,1386],{"verb":480,"entityId":243},{"verb":480,"entityId":285},{"verb":424,"entityId":231},[],[],[],{"id":1391,"title":1392,"statement":1393,"rationale":1394,"appliesTo":1395,"permits":1399,"intent":234,"supportingSections":1405,"references":1406},"an-api-key-records-its-use-only-when-presented","An API key records its use only when presented","An API key changes only when the API client it identifies presents it, which\nrecords when it was last used. Its name and secret never change, and the Owner\ndoes not edit a key.","The Owner reads a key's last use to decide whether the tool holding it is\nstill in use, so only that tool presenting it may move it.",[1396],{"type":1345,"entityId":285,"effect":608,"from":412,"to":412,"facts":1397,"contexts":1398},[],[],[1400],{"actorIds":1401,"related":1402,"self":403,"when":1404,"unattended":403,"configuredByEntityId":412},[],[1403],{"verb":424,"entityId":231},[],[],[],{"id":1408,"title":1409,"statement":1410,"rationale":1411,"appliesTo":1412,"permits":1416,"intent":234,"supportingSections":1422,"references":1423},"an-api-keys-secret-is-shown-only-to-its-owner-once","An API key's secret is shown only to its Owner, once","The secret of an API key is shown to the Owner who created it, at the moment\nit is created, and never again — not to them, and not to anyone else. Its name,\ncreation and last use stay visible to the Owner.","Anyone holding the secret can create links in the Owner's account. Showing it\nonce keeps the only copy outside the Product with the tool it was made for.",[1413],{"type":1345,"entityId":285,"effect":589,"from":412,"to":412,"facts":1414,"contexts":1415},[290],[],[1417],{"actorIds":1418,"related":1419,"self":403,"when":1421,"unattended":403,"configuredByEntityId":412},[],[1420],{"verb":480,"entityId":243},[],[],[],{"id":1425,"title":1426,"statement":1427,"rationale":1428,"appliesTo":1429,"permits":412,"intent":234,"supportingSections":1433,"references":1434},"clicks-never-identify-a-visitor","Clicks never identify a Visitor","A click keeps when it happened and the referring site, country and device it\ncame from — nothing that names, tracks or tells apart the person who followed\nthe link. Two clicks are never linked as coming from the same Visitor.","A Visitor follows a short address without an account and without agreeing to\nbe followed. Owners learn how a link travels; the Product does not learn who\nfollowed it.",[1430],{"type":1345,"entityId":313,"effect":412,"from":412,"to":412,"facts":1431,"contexts":1432},[],[],[],[],{"id":1436,"title":1437,"statement":1438,"rationale":1439,"appliesTo":1440,"permits":1444,"intent":234,"supportingSections":1445,"references":1446},"nobody-changes-a-links-slug","Nobody changes a link's slug","A link keeps the slug it was created with. Its Owner can change where it leads\nand when it expires, but never the short address itself.","Everyone who received the short address relies on it. A changed slug would\nbreak every copy already handed out and free the old one for another link.",[1441],{"type":1345,"entityId":321,"effect":608,"from":412,"to":412,"facts":1442,"contexts":1443},[325],[],[],[],[],{"id":1448,"title":1449,"statement":1450,"rationale":1451,"appliesTo":1452,"permits":1456,"intent":234,"supportingSections":1457,"references":1458},"nobody-deletes-a-link","Nobody deletes a link","A link can be disabled or left to expire, but never deleted — not by its\nOwner, not by an API client, and not by the Product. Its slug therefore never\nnames another link, and a taken slug stays taken.","Short addresses live on in printed pages, old messages and other people's\nposts. If a link could be deleted and its slug claimed again, an address handed\nout long ago could start sending Visitors somewhere its Owner never chose.",[1453],{"type":1345,"entityId":321,"effect":1242,"from":412,"to":412,"facts":1454,"contexts":1455},[],[],[],[],[],{"id":1460,"title":1461,"statement":1462,"rationale":1463,"appliesTo":1464,"permits":1468,"intent":234,"supportingSections":1478,"references":1479},"only-its-owner-or-its-expiry-changes-a-link","Only its Owner or its expiry changes a link","Only the Owner of a link changes where it leads, when it expires, or whether\nit is disabled. The one other change is the Product's own: expiring an active\nlink once the expiry its Owner set has passed.","A short address is trusted by everyone who receives it, so where it leads is\ndecided by the person accountable for it and by nobody else. API clients\ncreate links and never change them.",[1465],{"type":1345,"entityId":321,"effect":608,"from":412,"to":412,"facts":1466,"contexts":1467},[],[],[1469,1474],{"actorIds":1470,"related":1471,"self":403,"when":1473,"unattended":403,"configuredByEntityId":412},[],[1472],{"verb":480,"entityId":243},[],{"actorIds":1475,"related":1476,"self":403,"when":1477,"unattended":931,"configuredByEntityId":412},[],[],[],[],[],{"id":1481,"title":1482,"statement":1483,"rationale":1484,"appliesTo":1485,"permits":1489,"intent":234,"supportingSections":1495,"references":1496},"only-the-owner-creates-their-api-keys","Only the Owner creates their API keys","An API key is created in an Owner's account by that Owner, on the web. An API\nclient cannot create a key, for itself or for another tool.","The Owner is the one who decides which tools may create links in their\naccount, so letting a tool in is theirs alone.",[1486],{"type":1345,"entityId":285,"effect":662,"from":412,"to":412,"facts":1487,"contexts":1488},[],[],[1490],{"actorIds":1491,"related":1492,"self":403,"when":1494,"unattended":403,"configuredByEntityId":412},[],[1493],{"verb":480,"entityId":243},[],[],[],{"id":1498,"title":1499,"statement":1500,"rationale":1501,"appliesTo":1502,"permits":1506,"intent":234,"supportingSections":1512,"references":1513},"only-the-owner-revokes-an-api-key","Only the Owner revokes an API key","An API key is revoked only by the Owner who created it. An API client cannot\nrevoke the key it presents, or any other.","The Owner is the one who decides which tools may create links in their\naccount, so cutting a tool off is theirs alone.",[1503],{"type":1345,"entityId":285,"effect":1242,"from":412,"to":412,"facts":1504,"contexts":1505},[],[],[1507],{"actorIds":1508,"related":1509,"self":403,"when":1511,"unattended":403,"configuredByEntityId":412},[],[1510],{"verb":480,"entityId":243},[],[],[],{"id":1515,"title":1516,"statement":1517,"rationale":1518,"appliesTo":1519,"permits":1523,"intent":234,"supportingSections":1530,"references":1531},"only-the-owner-sees-a-links-clicks","Only the Owner sees a link's clicks","A link's analytics — its clicks, when they happened, and the referring sites,\ncountries and devices they came from — are shown to the link's Owner and to\nnobody else.","How often and from where a link is followed can reveal a campaign, an audience\nor a private conversation the Owner has not chosen to share.",[1520],{"type":1345,"entityId":313,"effect":589,"from":412,"to":412,"facts":1521,"contexts":1522},[],[],[1524],{"actorIds":1525,"related":1526,"self":403,"when":1529,"unattended":403,"configuredByEntityId":412},[],[1527,1528],{"verb":459,"entityId":321},{"verb":480,"entityId":243},[],[],[],[],{"scope":234,"method":234,"covered":1534,"exclusions":1535,"unmapped":1536,"limitations":1537},[],[],[],[],{"path":1539,"commit":1540},"blueprints\u002Furl-shortener","f474777f17005554bb7fd1f1e18189bfd01792bc",1791840534336]