[{"data":1,"prerenderedAt":142},["ShallowReactive",2],{"doc:\u002Fdocs\u002Fapi-keys":3},{"page":4,"toc":132,"updated":141},{"path":5,"title":6,"seoTitle":7,"description":8,"blocks":9},"\u002Fdocs\u002Fapi-keys","API keys and environments","API Keys, Allowed Origins and Environments","Create public and secret keys for development, staging and production, restrict public keys to your origins, and keep test traffic apart from real traffic.",[10,13,18,40,42,49,53,56,78,81,83,86,88,91,93,96,98,104,110,112,115,117,121,127,130],{"type":11,"text":12},"p","Keys identify your organization to Fingerly and decide what a request may do. Every key belongs to one **environment** and one **region**, and both are written into the key itself.",{"type":14,"level":15,"text":16,"id":17},"heading",2,"Environments","environments",{"type":19,"columns":20,"rows":25},"table",[21,22,23,24],"Environment","Public key prefix","Billed","Use it for",[26,31,35],[27,28,29,30],"Development","`fly_pk_us_development_`","No","Local development and CI.",[32,33,29,34],"Staging","`fly_pk_us_staging_`","Pre-release testing with realistic traffic.",[36,37,38,39],"Production","`fly_pk_us_production_`","Yes","Real visitors.",{"type":11,"text":41},"All three run exactly the same detection. What differs is billing, and everywhere results are read:",{"type":43,"items":44},"list",[45,46,47,48],"A secret key reads only events from its own environment.","Dashboards and the Events view filter by environment.","Webhook endpoints listen to **Live** (production) or **Test** (staging and development) traffic.","Usage counts non-production requests separately, as not billed.",{"type":50,"tone":51,"text":52},"callout","tip","Because the environment is part of the key, a development key shipped to production is visible in a code review.",{"type":14,"level":15,"text":54,"id":55},"Kinds of key","kinds-of-key",{"type":19,"columns":57,"rows":61},[58,59,60],"Kind","Where it lives","What it does",[62,66,70,74],[63,64,65],"Public, `fly_pk_`","Web pages and apps","Identifies visitors. Accepted only from its allowed origins in browsers.",[67,68,69],"Secret, `fly_sk_`","Your servers","Reads events. Refused from browsers.",[71,72,73],"Proxy, `fly_px_`","Your proxy","Forwards identify requests with visitor details. See [proxy integrations](\u002Fdocs\u002Fproxy-integrations).",[75,76,77],"Management, `fly_mk_`","Your automation","Manages keys, webhook endpoints and risk weights through the [management API](\u002Freference\u002Fmanagement\u002Foverview). Belongs to no environment. Refused from browsers.",{"type":14,"level":15,"text":79,"id":80},"Create a key","create-a-key",{"type":11,"text":82},"In the dashboard, open **Integration > SDK keys** and create a key. Choose its kind and environment, name it, and for a public key list its allowed origins. You can also set an expiry date. Proxy keys are issued separately, in **Integration > Proxy keys**.",{"type":50,"tone":84,"text":85},"warning","A secret key is shown once, when it is created. Copy it into your secret manager straight away. Fingerly stores only a hash of each key and cannot show it again.",{"type":11,"text":87},"Owners, admins and developers can create and revoke keys. To create keys from code, for example with each new staging environment, use the [management API](\u002Freference\u002Fmanagement\u002Fsdk-keys).",{"type":14,"level":15,"text":89,"id":90},"Management keys","management-keys",{"type":11,"text":92},"Management keys let automation manage your integration without a person signed in. Owners and admins issue them in **Integration > Management keys**, each acting with the `admin` or `developer` role. A management key is shown once, is refused from browsers, and cannot issue other management keys. See the [management API](\u002Freference\u002Fmanagement\u002Foverview).",{"type":14,"level":15,"text":94,"id":95},"Allowed origins","allowed-origins",{"type":11,"text":97},"A public key is accepted from a browser only when the page's origin exactly matches one of the key's allowed origins.",{"type":99,"samples":100},"code",[101],{"label":94,"lang":102,"code":103},"text","https:\u002F\u002Fshop.example.com\nhttps:\u002F\u002Fwww.example.com\nhttp:\u002F\u002Flocalhost:3000",{"type":43,"items":105},[106,107,108,109],"An origin is a scheme, a host and an optional port, with no path and no trailing slash.","Matching is exact: `https:\u002F\u002Fexample.com` does not allow `https:\u002F\u002Fwww.example.com`, and there are no wildcards.","A public key with no allowed origins refuses every browser request.","Native apps identify their platform instead of an origin, so mobile SDKs do not need one.",{"type":11,"text":111},"You can change a public key's allowed origins at any time from its row in **SDK keys**. The change applies within a minute.",{"type":14,"level":15,"text":113,"id":114},"Revoke a key","revoke-a-key",{"type":11,"text":116},"Revoking a key refuses it immediately and cannot be undone. Requests made with it afterwards fail with `401`, and each sends an [`identification.refused`](\u002Freference\u002Fwebhooks\u002Fidentification-refused) webhook with the reason `revoked_key`, so you can find any deployment still using it.",{"type":14,"level":118,"text":119,"id":120},3,"Rotating a key","rotating-a-key",{"type":43,"items":122},[123,124,125,126],"Create the new key in the same environment.","Deploy it everywhere the old one is used.","Watch the old key's usage fall to zero in **SDK keys**.","Revoke the old key.",{"type":14,"level":15,"text":128,"id":129},"Regions","regions",{"type":11,"text":131},"The region in a key, such as `us`, decides which regional API accepts it. A key is refused by any other region's API. See [regions and data residency](\u002Fdocs\u002Fregions).",[133,134,135,136,137,138,139,140],{"id":17,"text":16,"level":15},{"id":55,"text":54,"level":15},{"id":80,"text":79,"level":15},{"id":90,"text":89,"level":15},{"id":95,"text":94,"level":15},{"id":114,"text":113,"level":15},{"id":120,"text":119,"level":118},{"id":129,"text":128,"level":15},"2026-09-17T16:57:42.000Z",1789667797515]