[{"data":1,"prerenderedAt":1908},["ShallowReactive",2],{"navigation":3,"/sdks/rust":258,"/sdks/rust-surround":1903},[4,22,63,85,115,131,219,245],{"title":5,"path":6,"stem":7,"children":8,"page":21},"Getting Started","/getting-started","1.getting-started",[9,13,17],{"title":10,"path":11,"stem":12},"Introduction","/getting-started/introduction","1.getting-started/1.introduction",{"title":14,"path":15,"stem":16},"Quick Start","/getting-started/quick-start","1.getting-started/2.quick-start",{"title":18,"path":19,"stem":20},"Key Concepts","/getting-started/key-concepts","1.getting-started/3.key-concepts",false,{"title":23,"path":24,"stem":25,"children":26,"page":21},"Guides","/guides","2.guides",[27,31,35,39,43,47,51,55,59],{"title":28,"path":29,"stem":30},"Quick Share Guide","/guides/quick-share","2.guides/1.quick-share",{"title":32,"path":33,"stem":34},"Slack Integration","/guides/slack-integration","2.guides/2.slack-integration",{"title":36,"path":37,"stem":38},"Enterprise Setup","/guides/enterprise-setup","2.guides/3.enterprise-setup",{"title":40,"path":41,"stem":42},"Creating a Share","/guides/creating-a-share","2.guides/4.creating-a-share",{"title":44,"path":45,"stem":46},"Zero-Knowledge Custody","/guides/zero-knowledge-custody","2.guides/5.zero-knowledge-custody",{"title":48,"path":49,"stem":50},"Secure Requests","/guides/secure-requests","2.guides/6.secure-requests",{"title":52,"path":53,"stem":54},"Receiving a Secure Request","/guides/receiving-a-secure-request","2.guides/7.receiving-a-secure-request",{"title":56,"path":57,"stem":58},"SecurePaste","/guides/securepaste","2.guides/8.securepaste",{"title":60,"path":61,"stem":62},"Notifications","/guides/notifications","2.guides/9.notifications",{"title":64,"icon":65,"path":66,"stem":67,"children":68,"page":21},"Account","i-lucide-user-cog","/account","3.account",[69,73,77,81],{"title":70,"path":71,"stem":72},"Signing In","/account/signing-in","3.account/1.signing-in",{"title":74,"path":75,"stem":76},"Plans and Share Allowance","/account/plans-and-share-allowance","3.account/2.plans-and-share-allowance",{"title":78,"path":79,"stem":80},"Billing and Subscription","/account/billing-and-subscription","3.account/3.billing-and-subscription",{"title":82,"path":83,"stem":84},"Plans and Limits","/account/plans-and-limits","3.account/4.plans-and-limits",{"title":86,"icon":87,"path":88,"stem":89,"children":90,"page":21},"Teams","i-lucide-users","/teams","4.teams",[91,95,99,103,107,111],{"title":92,"path":93,"stem":94},"Teams and Contexts","/teams/teams-and-contexts","4.teams/1.teams-and-contexts",{"title":96,"path":97,"stem":98},"Members, Roles and Seats","/teams/members-roles-and-seats","4.teams/2.members-roles-and-seats",{"title":100,"path":101,"stem":102},"Joining a Team","/teams/joining-a-team","4.teams/3.joining-a-team",{"title":104,"path":105,"stem":106},"Custom Branding","/teams/custom-branding","4.teams/4.custom-branding",{"title":108,"path":109,"stem":110},"Policy and Audit","/teams/policy-and-audit","4.teams/5.policy-and-audit",{"title":112,"path":113,"stem":114},"Zero-Knowledge for Teams","/teams/zero-knowledge-for-teams","4.teams/6.zero-knowledge-for-teams",{"title":116,"path":117,"stem":118,"children":119,"icon":130},"Help","/help","5.help/0.index",[120,122,126],{"title":121,"path":117,"stem":118},"Help and Support",{"title":123,"path":124,"stem":125},"Link Not Working","/help/link-not-working","5.help/1.link-not-working",{"title":127,"path":128,"stem":129},"Error Messages","/help/error-messages","5.help/2.error-messages","i-lucide-life-buoy",{"title":132,"path":133,"stem":134,"children":135},"API Reference","/api","6.api/0.index",[136,137,141,167,189,193,211,215],{"title":132,"path":133,"stem":134},{"title":138,"path":139,"stem":140},"Authentication","/api/authentication","6.api/1.authentication",{"title":142,"path":143,"stem":144,"children":145},"Shares","/api/shares","6.api/2.shares/0.index",[146,147,151,155,159,163],{"title":142,"path":143,"stem":144},{"title":148,"path":149,"stem":150},"Create a share","/api/shares/create","6.api/2.shares/1.create",{"title":152,"path":153,"stem":154},"List shares","/api/shares/list","6.api/2.shares/2.list",{"title":156,"path":157,"stem":158},"Retrieve a share","/api/shares/retrieve","6.api/2.shares/3.retrieve",{"title":160,"path":161,"stem":162},"Expire a share","/api/shares/delete","6.api/2.shares/4.delete",{"title":164,"path":165,"stem":166},"Client-side encryption","/api/shares/client-side-encryption","6.api/2.shares/5.client-side-encryption",{"title":168,"path":169,"stem":170,"children":171},"Secure requests","/api/requests","6.api/3.requests/0.index",[172,173,177,181,185],{"title":168,"path":169,"stem":170},{"title":174,"path":175,"stem":176},"Create a request","/api/requests/create","6.api/3.requests/1.create",{"title":178,"path":179,"stem":180},"List and retrieve requests","/api/requests/list","6.api/3.requests/2.list",{"title":182,"path":183,"stem":184},"Read submissions","/api/requests/submissions","6.api/3.requests/3.submissions",{"title":186,"path":187,"stem":188},"Expire or delete a request","/api/requests/delete","6.api/3.requests/4.delete",{"title":190,"path":191,"stem":192},"Stats","/api/stats","6.api/4.stats",{"title":194,"path":195,"stem":196,"children":197},"Webhooks","/api/webhooks","6.api/5.webhooks/0.index",[198,199,203,207],{"title":194,"path":195,"stem":196},{"title":200,"path":201,"stem":202},"Event reference","/api/webhooks/events","6.api/5.webhooks/1.events",{"title":204,"path":205,"stem":206},"Verifying signatures","/api/webhooks/verifying-signatures","6.api/5.webhooks/2.verifying-signatures",{"title":208,"path":209,"stem":210},"Delivery and retries","/api/webhooks/delivery-and-retries","6.api/5.webhooks/3.delivery-and-retries",{"title":212,"path":213,"stem":214},"MCP server","/api/mcp","6.api/6.mcp",{"title":216,"path":217,"stem":218},"Errors and Rate Limits","/api/errors-and-limits","6.api/7.errors-and-limits",{"title":220,"path":221,"stem":222,"children":223},"SDKs","/sdks","7.sdks/0.index",[224,225,229,233,237,241],{"title":220,"path":221,"stem":222},{"title":226,"path":227,"stem":228},"Node SDK","/sdks/node","7.sdks/1.node",{"title":230,"path":231,"stem":232},"Python SDK","/sdks/python","7.sdks/2.python",{"title":234,"path":235,"stem":236},"Go SDK","/sdks/go","7.sdks/3.go",{"title":238,"path":239,"stem":240},"Rust SDK","/sdks/rust","7.sdks/4.rust",{"title":242,"path":243,"stem":244},"Conformance vectors","/sdks/conformance-vectors","7.sdks/5.conformance-vectors",{"title":246,"path":247,"stem":248,"children":249,"page":21},"Security","/security","8.security",[250,254],{"title":251,"path":252,"stem":253},"Encryption","/security/encryption","8.security/1.encryption",{"title":255,"path":256,"stem":257},"Compliance","/security/compliance","8.security/2.compliance",{"id":259,"title":238,"api":260,"body":261,"description":1898,"extension":1899,"links":260,"meta":1900,"navigation":457,"path":239,"seo":1901,"stem":240,"__hash__":1902},"docs/7.sdks/4.rust.md",null,{"type":262,"value":263,"toc":1887},"minimark",[264,274,295,300,325,328,366,392,408,411,415,747,754,760,764,770,885,908,944,948,1067,1070,1077,1084,1088,1215,1238,1245,1257,1263,1267,1353,1359,1365,1409,1425,1429,1561,1578,1582,1585,1726,1730,1737,1761,1772,1775,1789,1792,1871,1883],[265,266,267],"p",{},[268,269,273],"a",{"href":270,"rel":271},"https://github.com/CredenShare/credenshare-sdk-rust",[272],"nofollow","github.com/CredenShare/credenshare-sdk-rust",[265,275,276,280,281,284,285,284,288,284,291,294],{},[277,278,279],"code",{},"#![forbid(unsafe_code)]",", with primitives from RustCrypto — ",[277,282,283],{},"aes-gcm",", ",[277,286,287],{},"hkdf",[277,289,290],{},"p256",[277,292,293],{},"subtle"," — rather than anything hand-rolled. A crate whose whole claim is that it encrypts correctly is the wrong place to be clever.",[296,297,299],"h2",{"id":298},"installing","Installing",[301,302,307],"pre",{"className":303,"code":304,"language":305,"meta":306,"style":306},"language-bash shiki shiki-themes github-light github-dark github-dark","cargo add credenshare\n","bash","",[277,308,309],{"__ignoreMap":306},[310,311,314,318,322],"span",{"class":312,"line":313},"line",1,[310,315,317],{"class":316},"shcOC","cargo",[310,319,321],{"class":320},"sfrk1"," add",[310,323,324],{"class":320}," credenshare\n",[265,326,327],{},"A git dependency also works, if you want a specific tag or an unreleased fix:",[301,329,334],{"className":330,"code":331,"filename":332,"language":333,"meta":306,"style":306},"language-toml shiki shiki-themes github-light github-dark github-dark","[dependencies]\ncredenshare = { git = \"https://github.com/CredenShare/credenshare-sdk-rust\", tag = \"v0.1.3\" }\n","Cargo.toml","toml",[277,335,336,348],{"__ignoreMap":306},[310,337,338,342,345],{"class":312,"line":313},[310,339,341],{"class":340},"slsVL","[",[310,343,344],{"class":316},"dependencies",[310,346,347],{"class":340},"]\n",[310,349,351,354,357,360,363],{"class":312,"line":350},2,[310,352,353],{"class":340},"credenshare = { git = ",[310,355,356],{"class":320},"\"https://github.com/CredenShare/credenshare-sdk-rust\"",[310,358,359],{"class":340},", tag = ",[310,361,362],{"class":320},"\"v0.1.3\"",[310,364,365],{"class":340}," }\n",[265,367,368,369,373,374,377,378,381,382,381,385,381,388,391],{},"The MSRV is ",[370,371,372],"strong",{},"1.88",", and it comes from the optional ",[277,375,376],{},"client"," feature's dependency chain (",[277,379,380],{},"ureq"," → ",[277,383,384],{},"url",[277,386,387],{},"idna",[277,389,390],{},"icu_*",") rather than from the cryptography. Dropping that feature relaxes the floor, but not by much and not to nothing — the crate has never had a green build below 1.88 in any configuration, so treat a lower toolchain as untested rather than supported:",[301,393,395],{"className":330,"code":394,"language":333,"meta":306,"style":306},"credenshare = { default-features = false }\n",[277,396,397],{"__ignoreMap":306},[310,398,399,402,406],{"class":312,"line":313},[310,400,401],{"class":340},"credenshare = { default-features = ",[310,403,405],{"class":404},"suiK_","false",[310,407,365],{"class":340},[265,409,410],{},"That drops the HTTP client and compiles only the encryption, which is what you want if you post with your own client or run somewhere a TLS stack would be dead weight.",[296,412,414],{"id":413},"quickstart","Quickstart",[301,416,420],{"className":417,"code":418,"language":419,"meta":306,"style":306},"language-rust shiki shiki-themes github-light github-dark github-dark","use credenshare::{CredenShare, CreateParams, Field};\n\nfn main() -> Result\u003C(), credenshare::Error> {\n    let client = CredenShare::new(&std::env::var(\"CREDENSHARE_KEY\").unwrap())?;\n\n    let share = client.create_share(CreateParams {\n        title: \"Staging deploy credentials\".into(),\n        fields: vec![\n            Field::new(\"Username\", \"deploy-bot\", \"text\"),\n            Field::new(\"Password\", \"correct horse\", \"password\"),\n        ],\n        ..Default::default()\n    })?;\n\n    println!(\"{}\", share.link);\n    // https://crs.sh/aB3dEf12#1xK9...\n    Ok(())\n}\n","rust",[277,421,422,453,459,488,550,555,580,600,614,642,668,674,691,701,706,725,732,741],{"__ignoreMap":306},[310,423,424,428,431,434,437,440,442,445,447,450],{"class":312,"line":313},[310,425,427],{"class":426},"so5gQ","use",[310,429,430],{"class":316}," credenshare",[310,432,433],{"class":426},"::",[310,435,436],{"class":340},"{",[310,438,439],{"class":316},"CredenShare",[310,441,284],{"class":340},[310,443,444],{"class":316},"CreateParams",[310,446,284],{"class":340},[310,448,449],{"class":316},"Field",[310,451,452],{"class":340},"};\n",[310,454,455],{"class":312,"line":350},[310,456,458],{"emptyLinePlaceholder":457},true,"\n",[310,460,462,465,468,471,474,477,480,482,485],{"class":312,"line":461},3,[310,463,464],{"class":426},"fn",[310,466,467],{"class":316}," main",[310,469,470],{"class":340},"() ",[310,472,473],{"class":426},"->",[310,475,476],{"class":316}," Result",[310,478,479],{"class":340},"\u003C(), credenshare",[310,481,433],{"class":426},[310,483,484],{"class":316},"Error",[310,486,487],{"class":340},"> {\n",[310,489,491,494,497,500,503,505,508,511,514,517,519,522,524,527,529,532,535,538,541,544,547],{"class":312,"line":490},4,[310,492,493],{"class":426},"    let",[310,495,496],{"class":340}," client ",[310,498,499],{"class":426},"=",[310,501,502],{"class":316}," CredenShare",[310,504,433],{"class":426},[310,506,507],{"class":316},"new",[310,509,510],{"class":340},"(",[310,512,513],{"class":426},"&",[310,515,516],{"class":316},"std",[310,518,433],{"class":426},[310,520,521],{"class":316},"env",[310,523,433],{"class":426},[310,525,526],{"class":316},"var",[310,528,510],{"class":340},[310,530,531],{"class":320},"\"CREDENSHARE_KEY\"",[310,533,534],{"class":340},")",[310,536,537],{"class":426},".",[310,539,540],{"class":316},"unwrap",[310,542,543],{"class":340},"())",[310,545,546],{"class":426},"?",[310,548,549],{"class":340},";\n",[310,551,553],{"class":312,"line":552},5,[310,554,458],{"emptyLinePlaceholder":457},[310,556,558,560,563,565,568,570,573,575,577],{"class":312,"line":557},6,[310,559,493],{"class":426},[310,561,562],{"class":340}," share ",[310,564,499],{"class":426},[310,566,567],{"class":340}," client",[310,569,537],{"class":426},[310,571,572],{"class":316},"create_share",[310,574,510],{"class":340},[310,576,444],{"class":316},[310,578,579],{"class":340}," {\n",[310,581,583,586,589,592,594,597],{"class":312,"line":582},7,[310,584,585],{"class":340},"        title",[310,587,588],{"class":426},":",[310,590,591],{"class":320}," \"Staging deploy credentials\"",[310,593,537],{"class":426},[310,595,596],{"class":316},"into",[310,598,599],{"class":340},"(),\n",[310,601,603,606,608,611],{"class":312,"line":602},8,[310,604,605],{"class":340},"        fields",[310,607,588],{"class":426},[310,609,610],{"class":316}," vec!",[310,612,613],{"class":340},"[\n",[310,615,617,620,622,624,626,629,631,634,636,639],{"class":312,"line":616},9,[310,618,619],{"class":316},"            Field",[310,621,433],{"class":426},[310,623,507],{"class":316},[310,625,510],{"class":340},[310,627,628],{"class":320},"\"Username\"",[310,630,284],{"class":340},[310,632,633],{"class":320},"\"deploy-bot\"",[310,635,284],{"class":340},[310,637,638],{"class":320},"\"text\"",[310,640,641],{"class":340},"),\n",[310,643,645,647,649,651,653,656,658,661,663,666],{"class":312,"line":644},10,[310,646,619],{"class":316},[310,648,433],{"class":426},[310,650,507],{"class":316},[310,652,510],{"class":340},[310,654,655],{"class":320},"\"Password\"",[310,657,284],{"class":340},[310,659,660],{"class":320},"\"correct horse\"",[310,662,284],{"class":340},[310,664,665],{"class":320},"\"password\"",[310,667,641],{"class":340},[310,669,671],{"class":312,"line":670},11,[310,672,673],{"class":340},"        ],\n",[310,675,677,680,683,685,688],{"class":312,"line":676},12,[310,678,679],{"class":426},"        ..",[310,681,682],{"class":316},"Default",[310,684,433],{"class":426},[310,686,687],{"class":316},"default",[310,689,690],{"class":340},"()\n",[310,692,694,697,699],{"class":312,"line":693},13,[310,695,696],{"class":340},"    })",[310,698,546],{"class":426},[310,700,549],{"class":340},[310,702,704],{"class":312,"line":703},14,[310,705,458],{"emptyLinePlaceholder":457},[310,707,709,712,714,717,720,722],{"class":312,"line":708},15,[310,710,711],{"class":316},"    println!",[310,713,510],{"class":340},[310,715,716],{"class":320},"\"{}\"",[310,718,719],{"class":340},", share",[310,721,537],{"class":426},[310,723,724],{"class":340},"link);\n",[310,726,728],{"class":312,"line":727},16,[310,729,731],{"class":730},"sCsY4","    // https://crs.sh/aB3dEf12#1xK9...\n",[310,733,735,738],{"class":312,"line":734},17,[310,736,737],{"class":316},"    Ok",[310,739,740],{"class":340},"(())\n",[310,742,744],{"class":312,"line":743},18,[310,745,746],{"class":340},"}\n",[265,748,749,750,753],{},"The client is ",[370,751,752],{},"synchronous",". There is no async surface and no pluggable transport.",[265,755,756,759],{},[370,757,758],{},"That link is the secret."," The key rides in the fragment, which browsers never transmit. Anyone holding the link can read the content; we cannot, and cannot recover it for you.",[296,761,763],{"id":762},"the-field-object","The field object",[265,765,766,769],{},[277,767,768],{},"Field::new(key, value, type)"," is the constructor you want. If you write a struct literal instead, note the member names:",[301,771,773],{"className":417,"code":772,"language":419,"meta":306,"style":306},"pub struct Field {\n    pub key: String,\n    pub value: String,\n    #[serde(rename = \"type\")]\n    pub field_type: String,\n    #[serde(flatten, default, skip_serializing_if = \"Map::is_empty\")]\n    pub extra: Map\u003CString, Value>,\n}\n",[277,774,775,788,804,817,830,843,855,881],{"__ignoreMap":306},[310,776,777,780,783,786],{"class":312,"line":313},[310,778,779],{"class":426},"pub",[310,781,782],{"class":426}," struct",[310,784,785],{"class":316}," Field",[310,787,579],{"class":340},[310,789,790,793,796,798,801],{"class":312,"line":350},[310,791,792],{"class":426},"    pub",[310,794,795],{"class":340}," key",[310,797,588],{"class":426},[310,799,800],{"class":316}," String",[310,802,803],{"class":340},",\n",[310,805,806,808,811,813,815],{"class":312,"line":461},[310,807,792],{"class":426},[310,809,810],{"class":340}," value",[310,812,588],{"class":426},[310,814,800],{"class":316},[310,816,803],{"class":340},[310,818,819,822,824,827],{"class":312,"line":490},[310,820,821],{"class":340},"    #[serde(rename ",[310,823,499],{"class":426},[310,825,826],{"class":320}," \"type\"",[310,828,829],{"class":340},")]\n",[310,831,832,834,837,839,841],{"class":312,"line":552},[310,833,792],{"class":426},[310,835,836],{"class":340}," field_type",[310,838,588],{"class":426},[310,840,800],{"class":316},[310,842,803],{"class":340},[310,844,845,848,850,853],{"class":312,"line":557},[310,846,847],{"class":340},"    #[serde(flatten, default, skip_serializing_if ",[310,849,499],{"class":426},[310,851,852],{"class":320}," \"Map::is_empty\"",[310,854,829],{"class":340},[310,856,857,859,862,864,867,870,873,875,878],{"class":312,"line":582},[310,858,792],{"class":426},[310,860,861],{"class":340}," extra",[310,863,588],{"class":426},[310,865,866],{"class":316}," Map",[310,868,869],{"class":340},"\u003C",[310,871,872],{"class":316},"String",[310,874,284],{"class":340},[310,876,877],{"class":316},"Value",[310,879,880],{"class":340},">,\n",[310,882,883],{"class":312,"line":602},[310,884,746],{"class":340},[265,886,887,890,891,896,897,899,900,903,904,907],{},[277,888,889],{},"type"," is a Rust keyword, so the member is ",[370,892,893],{},[277,894,895],{},"field_type"," and serde renames it on the wire. A deserialised ",[277,898,449],{}," has no ",[277,901,902],{},".type"," to read. ",[277,905,906],{},"extra"," is declared last and flattened, so the three known members keep their declaration order on the wire — which the conformance vectors depend on.",[265,909,910,913,914,917,918,920,921,284,924,284,927,284,930,284,933,284,936,939,940,943],{},[277,911,912],{},"key"," is the ",[370,915,916],{},"visible label",", not an identifier — it is what the recipient reads. ",[277,919,895],{}," is one of ",[277,922,923],{},"text",[277,925,926],{},"password",[277,928,929],{},"date",[277,931,932],{},"multiline",[277,934,935],{},"markdown",[277,937,938],{},"source_code",", exported as ",[277,941,942],{},"credenshare::FIELD_TYPES",". Validation checks only that it is present, not that it is a member of that array — check against the constant if the value is dynamic.",[296,945,947],{"id":946},"creating","Creating",[301,949,951],{"className":417,"code":950,"language":419,"meta":306,"style":306},"let share = client.create_share(CreateParams {\n    title: \"Production database\".into(),\n    fields: vec![Field::new(\"Password\", \"s3cr3t\", \"password\")],\n    passcode: Some(\"hunter2\".into()),\n    ..Default::default()\n})?;\n",[277,952,953,974,990,1023,1045,1058],{"__ignoreMap":306},[310,954,955,958,960,962,964,966,968,970,972],{"class":312,"line":313},[310,956,957],{"class":426},"let",[310,959,562],{"class":340},[310,961,499],{"class":426},[310,963,567],{"class":340},[310,965,537],{"class":426},[310,967,572],{"class":316},[310,969,510],{"class":340},[310,971,444],{"class":316},[310,973,579],{"class":340},[310,975,976,979,981,984,986,988],{"class":312,"line":350},[310,977,978],{"class":340},"    title",[310,980,588],{"class":426},[310,982,983],{"class":320}," \"Production database\"",[310,985,537],{"class":426},[310,987,596],{"class":316},[310,989,599],{"class":340},[310,991,992,995,997,999,1001,1003,1005,1007,1009,1011,1013,1016,1018,1020],{"class":312,"line":461},[310,993,994],{"class":340},"    fields",[310,996,588],{"class":426},[310,998,610],{"class":316},[310,1000,341],{"class":340},[310,1002,449],{"class":316},[310,1004,433],{"class":426},[310,1006,507],{"class":316},[310,1008,510],{"class":340},[310,1010,655],{"class":320},[310,1012,284],{"class":340},[310,1014,1015],{"class":320},"\"s3cr3t\"",[310,1017,284],{"class":340},[310,1019,665],{"class":320},[310,1021,1022],{"class":340},")],\n",[310,1024,1025,1028,1030,1033,1035,1038,1040,1042],{"class":312,"line":490},[310,1026,1027],{"class":340},"    passcode",[310,1029,588],{"class":426},[310,1031,1032],{"class":316}," Some",[310,1034,510],{"class":340},[310,1036,1037],{"class":320},"\"hunter2\"",[310,1039,537],{"class":426},[310,1041,596],{"class":316},[310,1043,1044],{"class":340},"()),\n",[310,1046,1047,1050,1052,1054,1056],{"class":312,"line":552},[310,1048,1049],{"class":426},"    ..",[310,1051,682],{"class":316},[310,1053,433],{"class":426},[310,1055,687],{"class":316},[310,1057,690],{"class":340},[310,1059,1060,1063,1065],{"class":312,"line":557},[310,1061,1062],{"class":340},"})",[310,1064,546],{"class":426},[310,1066,549],{"class":340},[265,1068,1069],{},"There is no custody option on this client. Node, Python and Go can wrap the content key to your credential's custody key on create, so the share stays readable from the dashboard; a Rust-created share is readable only from its link.",[265,1071,1072,1073,1076],{},"A passcode is mixed into the ",[370,1074,1075],{},"content key derivation",", not just checked by the server — so it is not a server-side gate you could bypass, and a passcode-protected share cannot be opened from the link alone. The server receives only a one-way verifier. Send the link and the passcode over different channels.",[265,1078,1079,1080,1083],{},"Requires the ",[277,1081,1082],{},"shares:write"," scope.",[296,1085,1087],{"id":1086},"listing-and-expiring","Listing and expiring",[301,1089,1091],{"className":417,"code":1090,"language":419,"meta":306,"style":306},"let page = client.list_shares(50, 1)?;\n\nclient.for_each_share(100, |s| {\n    println!(\"{} {:?}\", s.short_code, s.expired_at);\n    Ok(())\n})?;\n\nclient.expire_share(\"aB3dEf12\")?;\n",[277,1092,1093,1125,1129,1155,1177,1183,1191,1195],{"__ignoreMap":306},[310,1094,1095,1097,1100,1102,1104,1106,1109,1111,1114,1116,1119,1121,1123],{"class":312,"line":313},[310,1096,957],{"class":426},[310,1098,1099],{"class":340}," page ",[310,1101,499],{"class":426},[310,1103,567],{"class":340},[310,1105,537],{"class":426},[310,1107,1108],{"class":316},"list_shares",[310,1110,510],{"class":340},[310,1112,1113],{"class":404},"50",[310,1115,284],{"class":340},[310,1117,1118],{"class":404},"1",[310,1120,534],{"class":340},[310,1122,546],{"class":426},[310,1124,549],{"class":340},[310,1126,1127],{"class":312,"line":350},[310,1128,458],{"emptyLinePlaceholder":457},[310,1130,1131,1133,1135,1138,1140,1143,1145,1148,1151,1153],{"class":312,"line":461},[310,1132,376],{"class":340},[310,1134,537],{"class":426},[310,1136,1137],{"class":316},"for_each_share",[310,1139,510],{"class":340},[310,1141,1142],{"class":404},"100",[310,1144,284],{"class":340},[310,1146,1147],{"class":426},"|",[310,1149,1150],{"class":340},"s",[310,1152,1147],{"class":426},[310,1154,579],{"class":340},[310,1156,1157,1159,1161,1164,1167,1169,1172,1174],{"class":312,"line":490},[310,1158,711],{"class":316},[310,1160,510],{"class":340},[310,1162,1163],{"class":320},"\"{} {:?}\"",[310,1165,1166],{"class":340},", s",[310,1168,537],{"class":426},[310,1170,1171],{"class":340},"short_code, s",[310,1173,537],{"class":426},[310,1175,1176],{"class":340},"expired_at);\n",[310,1178,1179,1181],{"class":312,"line":552},[310,1180,737],{"class":316},[310,1182,740],{"class":340},[310,1184,1185,1187,1189],{"class":312,"line":557},[310,1186,1062],{"class":340},[310,1188,546],{"class":426},[310,1190,549],{"class":340},[310,1192,1193],{"class":312,"line":582},[310,1194,458],{"emptyLinePlaceholder":457},[310,1196,1197,1199,1201,1204,1206,1209,1211,1213],{"class":312,"line":602},[310,1198,376],{"class":340},[310,1200,537],{"class":426},[310,1202,1203],{"class":316},"expire_share",[310,1205,510],{"class":340},[310,1207,1208],{"class":320},"\"aB3dEf12\"",[310,1210,534],{"class":340},[310,1212,546],{"class":426},[310,1214,549],{"class":340},[265,1216,1217,1219,1220,1223,1224,1227,1228,1219,1230,1223,1232,1234,1235,1237],{},[277,1218,1108],{}," and ",[277,1221,1222],{},"get_share"," need ",[277,1225,1226],{},"shares:read","; ",[277,1229,572],{},[277,1231,1203],{},[277,1233,1082],{},". There is no hierarchy between them, so a key minted with only ",[277,1236,1082],{}," fails on a list call — the most common first surprise.",[265,1239,1240,1241,1244],{},"Both return ",[370,1242,1243],{},"metadata only",", never content and never a key. A short code belonging to another account reports exactly as one that does not exist.",[265,1246,1247,1249,1250,1253,1254,1256],{},[277,1248,1203],{}," ",[370,1251,1252],{},"removes"," the share rather than flagging it, so a later ",[277,1255,1222],{}," fails as not-found. A share you expired and one that never existed are indistinguishable afterwards.",[265,1258,1259,1262],{},[277,1260,1261],{},"link_for(short_code, content_key)"," assembles a recipient link for a short code you already hold, if you kept the content key.",[296,1264,1266],{"id":1265},"verifying-webhooks","Verifying webhooks",[301,1268,1270],{"className":417,"code":1269,"language":419,"meta":306,"style":306},"use credenshare::webhooks;\n\nwebhooks::verify(\n    raw_body,                       // &[u8], before any decoding\n    header,                         // the X-CredenShare-Signature value\n    &[&webhook_secret],\n    &webhooks::Options::default(),\n)?;\n",[277,1271,1272,1283,1287,1300,1308,1316,1328,1345],{"__ignoreMap":306},[310,1273,1274,1276,1278,1280],{"class":312,"line":313},[310,1275,427],{"class":426},[310,1277,430],{"class":316},[310,1279,433],{"class":426},[310,1281,1282],{"class":340},"webhooks;\n",[310,1284,1285],{"class":312,"line":350},[310,1286,458],{"emptyLinePlaceholder":457},[310,1288,1289,1292,1294,1297],{"class":312,"line":461},[310,1290,1291],{"class":316},"webhooks",[310,1293,433],{"class":426},[310,1295,1296],{"class":316},"verify",[310,1298,1299],{"class":340},"(\n",[310,1301,1302,1305],{"class":312,"line":490},[310,1303,1304],{"class":340},"    raw_body,                       ",[310,1306,1307],{"class":730},"// &[u8], before any decoding\n",[310,1309,1310,1313],{"class":312,"line":552},[310,1311,1312],{"class":340},"    header,                         ",[310,1314,1315],{"class":730},"// the X-CredenShare-Signature value\n",[310,1317,1318,1321,1323,1325],{"class":312,"line":557},[310,1319,1320],{"class":426},"    &",[310,1322,341],{"class":340},[310,1324,513],{"class":426},[310,1326,1327],{"class":340},"webhook_secret],\n",[310,1329,1330,1332,1334,1336,1339,1341,1343],{"class":312,"line":582},[310,1331,1320],{"class":426},[310,1333,1291],{"class":316},[310,1335,433],{"class":426},[310,1337,1338],{"class":316},"Options",[310,1340,433],{"class":426},[310,1342,687],{"class":316},[310,1344,599],{"class":340},[310,1346,1347,1349,1351],{"class":312,"line":602},[310,1348,534],{"class":340},[310,1350,546],{"class":426},[310,1352,549],{"class":340},[265,1354,1355,1358],{},[370,1356,1357],{},"Verify the raw body."," Re-serialising decoded JSON changes the bytes — key order, spacing, escapes — and the signature will not match.",[265,1360,1361,1364],{},[370,1362,1363],{},"Pass both secrets while rotating."," For 24 hours after a rotation, deliveries carry both signatures:",[301,1366,1368],{"className":417,"code":1367,"language":419,"meta":306,"style":306},"webhooks::verify(raw_body, header, &[&new_secret, &old_secret], &Default::default())?;\n",[277,1369,1370],{"__ignoreMap":306},[310,1371,1372,1374,1376,1378,1381,1383,1385,1387,1390,1392,1395,1397,1399,1401,1403,1405,1407],{"class":312,"line":313},[310,1373,1291],{"class":316},[310,1375,433],{"class":426},[310,1377,1296],{"class":316},[310,1379,1380],{"class":340},"(raw_body, header, ",[310,1382,513],{"class":426},[310,1384,341],{"class":340},[310,1386,513],{"class":426},[310,1388,1389],{"class":340},"new_secret, ",[310,1391,513],{"class":426},[310,1393,1394],{"class":340},"old_secret], ",[310,1396,513],{"class":426},[310,1398,682],{"class":316},[310,1400,433],{"class":426},[310,1402,687],{"class":316},[310,1404,543],{"class":340},[310,1406,546],{"class":426},[310,1408,549],{"class":340},[265,1410,1411,1413,1414,1417,1418,1421,1422,537],{},[277,1412,1296],{}," returns ",[277,1415,1416],{},"Result\u003C(), VerificationError>"," — there is no boolean to accidentally ignore. The header name is ",[277,1419,1420],{},"webhooks::SIGNATURE_HEADER"," and the ±5-minute window is ",[277,1423,1424],{},"DEFAULT_TOLERANCE_SECONDS",[296,1426,1428],{"id":1427},"configuration","Configuration",[301,1430,1432],{"className":417,"code":1431,"language":419,"meta":306,"style":306},"use credenshare::ClientOptions;\n\nlet client = CredenShare::with_options(&credential, ClientOptions {\n    base_url: \"https://api.credenshare.io/v1\".into(),\n    link_origin: \"https://crs.sh\".into(),\n    timeout: std::time::Duration::from_secs(30),\n    max_retries: 2,\n})?;\n",[277,1433,1434,1447,1451,1477,1493,1509,1541,1553],{"__ignoreMap":306},[310,1435,1436,1438,1440,1442,1445],{"class":312,"line":313},[310,1437,427],{"class":426},[310,1439,430],{"class":316},[310,1441,433],{"class":426},[310,1443,1444],{"class":316},"ClientOptions",[310,1446,549],{"class":340},[310,1448,1449],{"class":312,"line":350},[310,1450,458],{"emptyLinePlaceholder":457},[310,1452,1453,1455,1457,1459,1461,1463,1466,1468,1470,1473,1475],{"class":312,"line":461},[310,1454,957],{"class":426},[310,1456,496],{"class":340},[310,1458,499],{"class":426},[310,1460,502],{"class":316},[310,1462,433],{"class":426},[310,1464,1465],{"class":316},"with_options",[310,1467,510],{"class":340},[310,1469,513],{"class":426},[310,1471,1472],{"class":340},"credential, ",[310,1474,1444],{"class":316},[310,1476,579],{"class":340},[310,1478,1479,1482,1484,1487,1489,1491],{"class":312,"line":490},[310,1480,1481],{"class":340},"    base_url",[310,1483,588],{"class":426},[310,1485,1486],{"class":320}," \"https://api.credenshare.io/v1\"",[310,1488,537],{"class":426},[310,1490,596],{"class":316},[310,1492,599],{"class":340},[310,1494,1495,1498,1500,1503,1505,1507],{"class":312,"line":552},[310,1496,1497],{"class":340},"    link_origin",[310,1499,588],{"class":426},[310,1501,1502],{"class":320}," \"https://crs.sh\"",[310,1504,537],{"class":426},[310,1506,596],{"class":316},[310,1508,599],{"class":340},[310,1510,1511,1514,1516,1519,1521,1524,1526,1529,1531,1534,1536,1539],{"class":312,"line":557},[310,1512,1513],{"class":340},"    timeout",[310,1515,588],{"class":426},[310,1517,1518],{"class":316}," std",[310,1520,433],{"class":426},[310,1522,1523],{"class":316},"time",[310,1525,433],{"class":426},[310,1527,1528],{"class":316},"Duration",[310,1530,433],{"class":426},[310,1532,1533],{"class":316},"from_secs",[310,1535,510],{"class":340},[310,1537,1538],{"class":404},"30",[310,1540,641],{"class":340},[310,1542,1543,1546,1548,1551],{"class":312,"line":582},[310,1544,1545],{"class":340},"    max_retries",[310,1547,588],{"class":426},[310,1549,1550],{"class":404}," 2",[310,1552,803],{"class":340},[310,1554,1555,1557,1559],{"class":312,"line":602},[310,1556,1062],{"class":340},[310,1558,546],{"class":426},[310,1560,549],{"class":340},[265,1562,1563,1566,1567,1569,1570,1573,1574,1577],{},[277,1564,1565],{},"link_origin"," changes only the links this client assembles — what ",[277,1568,572],{}," returns and what ",[277,1571,1572],{},"link_for"," builds; it is never sent to the API. The SDK reads no environment variables — ",[277,1575,1576],{},"std::env::var"," above is your own read.",[296,1579,1581],{"id":1580},"rough-edges","Rough edges",[265,1583,1584],{},"Real behaviour worth knowing before it surprises you.",[1586,1587,1588,1634,1655,1667,1690,1720],"ul",{},[1589,1590,1591,1599,1600,1603,1604,1607,1608,1610,1611,1614,1615,1618,1619,1621,1622,1625,1626,1629,1630,1633],"li",{},[370,1592,1593,1595,1596],{},[277,1594,449],{}," gained a member, so a struct literal needs ",[277,1597,1598],{},"..Default::default()"," — or use ",[277,1601,1602],{},"Field::new",". ",[277,1605,1606],{},"Eq"," is implemented, so an ",[277,1609,1606],{}," bound is fine; ",[277,1612,1613],{},"Hash"," is not, because ",[277,1616,1617],{},"serde_json::Value"," has none, so ",[277,1620,449],{}," still cannot key a ",[277,1623,1624],{},"HashSet"," or ",[277,1627,1628],{},"BTreeMap",". Key on the ",[277,1631,1632],{},"(key, value, field_type)"," tuple for that.",[1589,1635,1636,1249,1639,1219,1641,1643,1644,1219,1647,1650,1651,1654],{},[370,1637,1638],{},"A short code that is not opaque is refused, not escaped.",[277,1640,1222],{},[277,1642,1203],{}," validate first — 1 to 64 characters, alphanumeric plus ",[277,1645,1646],{},"-",[277,1648,1649],{},"_"," — and return ",[277,1652,1653],{},"Error::InvalidArgument"," for anything else, so a crafted value never reaches the wire. This is the one client that rejects rather than encodes.",[1589,1656,1657,1662,1663,1666],{},[370,1658,1659,1661],{},[277,1660,1137],{}," can fail for a paging reason."," It refuses a response echoing a page number other than the one requested, and caps the walk at ",[277,1664,1665],{},"MAX_PAGES"," (100,000, re-exported from the crate root), rather than trusting the server to end it. Node and Python behave the same way; Go has the page-echo guard but no ceiling.",[1589,1668,1669,1219,1679,1413,1682,1685,1686,1689],{},[370,1670,1671,1674,1675,1678],{},[277,1672,1673],{},"Error::Internal"," carries no ",[277,1676,1677],{},"ApiDetails",",",[277,1680,1681],{},"Error::details()",[277,1683,1684],{},"None"," for it. ",[277,1687,1688],{},"read_link"," returns that variant and always fails.",[1589,1691,1692,1249,1698,1219,1701,1704,1705,1708,1709,1219,1712,1715,1716,1719],{},[370,1693,1694,1697],{},[277,1695,1696],{},"SeedKeypair","'s private halves are behind accessors and zeroized on drop.",[277,1699,1700],{},"seed",[277,1702,1703],{},"scalar"," are ",[277,1706,1707],{},"pub(crate)",", reachable only through ",[277,1710,1711],{},"seed()",[277,1713,1714],{},"private_scalar()",", so the hand-written ",[277,1717,1718],{},"Debug"," is no longer the only thing guarding them.",[1589,1721,1722,1725],{},[370,1723,1724],{},"A webhook secret with a trailing newline fails."," The blank check trims, but the HMAC is keyed with the untrimmed string. Rust, Python and Go behave this way — trim it yourself. Node now refuses such a secret by name.",[296,1727,1729],{"id":1728},"checking-your-build","Checking your build",[265,1731,1732,1733,1736],{},"The crate declares a ",[277,1734,1735],{},"credenshare-conformance"," binary. Inside a clone:",[301,1738,1740],{"className":303,"code":1739,"language":305,"meta":306,"style":306},"cargo run --bin credenshare-conformance -- -v\n",[277,1741,1742],{"__ignoreMap":306},[310,1743,1744,1746,1749,1752,1755,1758],{"class":312,"line":313},[310,1745,317],{"class":316},[310,1747,1748],{"class":320}," run",[310,1750,1751],{"class":404}," --bin",[310,1753,1754],{"class":320}," credenshare-conformance",[310,1756,1757],{"class":404}," --",[310,1759,1760],{"class":404}," -v\n",[265,1762,1763,1764,1767,1768,1771],{},"The ",[277,1765,1766],{},"--"," matters: a bare ",[277,1769,1770],{},"-v"," is consumed by cargo as its own verbosity flag and never reaches the binary.",[265,1773,1774],{},"Cargo does not build or expose a dependency's binary targets, so that command is not available to a project that merely depends on the crate. From outside a clone, either install the binary:",[301,1776,1778],{"className":303,"code":1777,"language":305,"meta":306,"style":306},"cargo install credenshare\n",[277,1779,1780],{"__ignoreMap":306},[310,1781,1782,1784,1787],{"class":312,"line":313},[310,1783,317],{"class":316},[310,1785,1786],{"class":320}," install",[310,1788,324],{"class":320},[265,1790,1791],{},"or call the conformance module from your own test suite, which is the better option for a deployment gate:",[301,1793,1795],{"className":417,"code":1794,"language":419,"meta":306,"style":306},"let (passed, failures) = credenshare::conformance::run(false, &mut |_| {})?;\nassert!(failures.is_empty(), \"{passed} passed, {} failed\", failures.len());\n",[277,1796,1797,1841],{"__ignoreMap":306},[310,1798,1799,1801,1804,1806,1808,1810,1813,1815,1818,1820,1822,1824,1827,1830,1832,1834,1837,1839],{"class":312,"line":313},[310,1800,957],{"class":426},[310,1802,1803],{"class":340}," (passed, failures) ",[310,1805,499],{"class":426},[310,1807,430],{"class":316},[310,1809,433],{"class":426},[310,1811,1812],{"class":316},"conformance",[310,1814,433],{"class":426},[310,1816,1817],{"class":316},"run",[310,1819,510],{"class":340},[310,1821,405],{"class":404},[310,1823,284],{"class":340},[310,1825,1826],{"class":426},"&mut",[310,1828,1829],{"class":426}," |",[310,1831,1649],{"class":340},[310,1833,1147],{"class":426},[310,1835,1836],{"class":340}," {})",[310,1838,546],{"class":426},[310,1840,549],{"class":340},[310,1842,1843,1846,1849,1851,1854,1857,1860,1863,1865,1868],{"class":312,"line":350},[310,1844,1845],{"class":316},"assert!",[310,1847,1848],{"class":340},"(failures",[310,1850,537],{"class":426},[310,1852,1853],{"class":316},"is_empty",[310,1855,1856],{"class":340},"(), ",[310,1858,1859],{"class":320},"\"{passed} passed, {} failed\"",[310,1861,1862],{"class":340},", failures",[310,1864,537],{"class":426},[310,1866,1867],{"class":316},"len",[310,1869,1870],{"class":340},"());\n",[265,1872,1873,1876,1877,1880,1881,537],{},[277,1874,1875],{},"conformance::VECTORS_JSON"," is the fixture itself, embedded with ",[277,1878,1879],{},"include_str!",". See ",[268,1882,242],{"href":243},[1884,1885,1886],"style",{},"html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":306,"searchDepth":313,"depth":350,"links":1888},[1889,1890,1891,1892,1893,1894,1895,1896,1897],{"id":298,"depth":350,"text":299},{"id":413,"depth":350,"text":414},{"id":762,"depth":350,"text":763},{"id":946,"depth":350,"text":947},{"id":1086,"depth":350,"text":1087},{"id":1265,"depth":350,"text":1266},{"id":1427,"depth":350,"text":1428},{"id":1580,"depth":350,"text":1581},{"id":1728,"depth":350,"text":1729},"The official Rust client — encrypts locally, assembles the link, verifies webhooks. Crypto usable without the HTTP stack.","md",{},{"title":238,"description":1898},"sNZl5ZH8PTGP79IpJQB1n9FwdDLbp7q8NDpXv4swgIg",[1904,1906],{"title":234,"path":235,"stem":236,"description":1905,"children":-1},"The official Go client — encrypts locally, assembles the link, verifies webhooks. Standard library only.",{"title":242,"path":243,"stem":244,"description":1907,"children":-1},"The fixture every CredenShare client must reproduce — what it covers, how to run it, and what it deliberately does not test.",1788908851457]