{"id":"salto.external-api","app":"salto","title":"Salto API keys and permissions","summary":"Grant only the read, PIN-write, guest-link or door-open capabilities an integration needs.","url":"https://www.simultem-apps.com/wiki/salto#external-api","apiUrl":"https://www.simultem-apps.com/api/wiki/v1/articles/salto.external-api","resourceUri":"wiki://salto/external-api","revision":"2026-11-02.1","lastReviewedAt":"2026-11-02","keywords":["API keys","pin:read","pin:write","guest:manage","door:open","expiry","revoke","includeEntrances","accessId","entrance PINs","ovikoodit"],"sections":[{"title":"Manage integration keys","steps":["Open API & guest access in an authorized account context.","Name the integration and choose its permissions: Read PINs, Generate and set PINs, Manage guest links and/or Open doors.","Create the key and copy the full credential immediately into a server-side secret manager.","Review the key prefix, permissions and expiry in the list.","Revoke a key when retiring or replacing it."],"notes":["The public wiki API does not grant any Salto operational permissions. Salto operational APIs require their own credentials and access checks."]},{"title":"PIN and guest-link endpoints","steps":["Send Authorization: Bearer YOUR_API_KEY from your backend. Keys expire after one year and cannot read configuration or provider credentials.","Use GET /api/salto/reservation-pin?accountCode=ACCOUNT&reservationId=RESERVATION with pin:read to read eligible reservation PINs. Reads do not generate a PIN.","Add &includeEntrances=true to that GET to include explicitly mapped property entrance PINs. The response contains pin, testMode and entrances: an array of {id, name, pin, swipeEnabled}. These entries represent entrance users/access sets, so three physical doors do not necessarily mean three PIN entries.","Use PUT /api/salto/pin-mutation?accountCode=ACCOUNT with pin:write and mode (generate or custom), siteId, userId, reservationId, propertyId and unitId for a reservation change. For custom mode, also provide pin. User-level changes can omit reservationId, propertyId and unitId, but still require an existing user mapping and cannot create or change mappings.","With guest:manage, use POST or GET /api/salto/guest-links?accountCode=ACCOUNT&reservationId=RESERVATION to create/list links; DELETE with {\"id\":\"LINK_ID\"} revokes one. POST can include {\"language\":\"fi\"}."],"notes":["Keys share a 120-request/minute budget. Opening attempts are additionally limited; respect Retry-After. Do not automatically retry a door-opening command.","Operational responses can be 401/403 for credentials/access, 409 for unavailable access or hardware/setup, 429 for limits and 502/503 for upstream/storage failure. Investigate uncertain writes before retrying."]},{"title":"List doors and request an opening","steps":["With door:open, call GET /api/salto/open?accountCode=ACCOUNT&reservationId=RESERVATION. It returns {ok, doors: [{id, name}], testMode}; it does not return PINs or an accessId field.","POST to the same URL with {\"doorId\":\"DOOR_ID\"} to request opening one of the currently allowed doors. An API-key caller can omit accessId; the server resolves an eligible room or entrance source.","An optional accessId selects a specific access set. Use an entrance id from the includeEntrances PIN response, or an accesses[].id from the guest access response when using a guest link. Do not substitute a door ID or invent an access-set ID.","The guest-facing GET /api/salto/guest/pin and POST /api/salto/guest/open use the personal guest-link bearer token. The guest response includes accesses with id, kind, name, pin and doors; the opening body can include doorId and accessId. Keep account API keys on your backend.","An opening request is checked against the current stay, mappings, Salto groups and schedules, IQ policy and lock/IQ availability. Success means the command was sent; it does not confirm the physical door position."],"notes":[],"example":"GET /api/salto/reservation-pin?accountCode=ACCOUNT&reservationId=RESERVATION&includeEntrances=true\nGET /api/salto/open?accountCode=ACCOUNT&reservationId=RESERVATION\nPOST /api/salto/open?accountCode=ACCOUNT&reservationId=RESERVATION\n{\"doorId\":\"DOOR_ID\"}"}],"text":"# Salto: Salto API keys and permissions\n\nGrant only the read, PIN-write, guest-link or door-open capabilities an integration needs.\n\n## Manage integration keys\n\n1. Open API & guest access in an authorized account context.\n\n2. Name the integration and choose its permissions: Read PINs, Generate and set PINs, Manage guest links and/or Open doors.\n\n3. Create the key and copy the full credential immediately into a server-side secret manager.\n\n4. Review the key prefix, permissions and expiry in the list.\n\n5. Revoke a key when retiring or replacing it.\n\nNote: The public wiki API does not grant any Salto operational permissions. Salto operational APIs require their own credentials and access checks.\n\n## PIN and guest-link endpoints\n\n1. Send Authorization: Bearer YOUR_API_KEY from your backend. Keys expire after one year and cannot read configuration or provider credentials.\n\n2. Use GET /api/salto/reservation-pin?accountCode=ACCOUNT&reservationId=RESERVATION with pin:read to read eligible reservation PINs. Reads do not generate a PIN.\n\n3. Add &includeEntrances=true to that GET to include explicitly mapped property entrance PINs. The response contains pin, testMode and entrances: an array of {id, name, pin, swipeEnabled}. These entries represent entrance users/access sets, so three physical doors do not necessarily mean three PIN entries.\n\n4. Use PUT /api/salto/pin-mutation?accountCode=ACCOUNT with pin:write and mode (generate or custom), siteId, userId, reservationId, propertyId and unitId for a reservation change. For custom mode, also provide pin. User-level changes can omit reservationId, propertyId and unitId, but still require an existing user mapping and cannot create or change mappings.\n\n5. With guest:manage, use POST or GET /api/salto/guest-links?accountCode=ACCOUNT&reservationId=RESERVATION to create/list links; DELETE with {\"id\":\"LINK_ID\"} revokes one. POST can include {\"language\":\"fi\"}.\n\nNote: Keys share a 120-request/minute budget. Opening attempts are additionally limited; respect Retry-After. Do not automatically retry a door-opening command.\n\nNote: Operational responses can be 401/403 for credentials/access, 409 for unavailable access or hardware/setup, 429 for limits and 502/503 for upstream/storage failure. Investigate uncertain writes before retrying.\n\n## List doors and request an opening\n\n1. With door:open, call GET /api/salto/open?accountCode=ACCOUNT&reservationId=RESERVATION. It returns {ok, doors: [{id, name}], testMode}; it does not return PINs or an accessId field.\n\n2. POST to the same URL with {\"doorId\":\"DOOR_ID\"} to request opening one of the currently allowed doors. An API-key caller can omit accessId; the server resolves an eligible room or entrance source.\n\n3. An optional accessId selects a specific access set. Use an entrance id from the includeEntrances PIN response, or an accesses[].id from the guest access response when using a guest link. Do not substitute a door ID or invent an access-set ID.\n\n4. The guest-facing GET /api/salto/guest/pin and POST /api/salto/guest/open use the personal guest-link bearer token. The guest response includes accesses with id, kind, name, pin and doors; the opening body can include doorId and accessId. Keep account API keys on your backend.\n\n5. An opening request is checked against the current stay, mappings, Salto groups and schedules, IQ policy and lock/IQ availability. Success means the command was sent; it does not confirm the physical door position.\n\nExample:\n\n```text\n\nGET /api/salto/reservation-pin?accountCode=ACCOUNT&reservationId=RESERVATION&includeEntrances=true\nGET /api/salto/open?accountCode=ACCOUNT&reservationId=RESERVATION\nPOST /api/salto/open?accountCode=ACCOUNT&reservationId=RESERVATION\n{\"doorId\":\"DOOR_ID\"}\n\n```","related":[{"id":"salto.main-entrances","app":"salto","title":"Main entrance doors and eligible units","summary":"Choose which shared entrance doors appear for guests of mapped units.","url":"https://www.simultem-apps.com/wiki/salto#main-entrances","apiUrl":"https://www.simultem-apps.com/api/wiki/v1/articles/salto.main-entrances","resourceUri":"wiki://salto/main-entrances","revision":"2026-11-02.1","lastReviewedAt":"2026-11-02"},{"id":"salto.guest-links","app":"salto","title":"Personal guest door-access pages","summary":"Create, use and revoke reservation-scoped links with PIN and remote-opening controls.","url":"https://www.simultem-apps.com/wiki/salto#guest-links","apiUrl":"https://www.simultem-apps.com/api/wiki/v1/articles/salto.guest-links","resourceUri":"wiki://salto/guest-links","revision":"2026-11-02.1","lastReviewedAt":"2026-11-02"},{"id":"salto.reservation-pins","app":"salto","title":"Generate, set and inspect reservation PINs","summary":"Check reservation eligibility, unit mapping and stay dates before changing access.","url":"https://www.simultem-apps.com/wiki/salto#reservation-pins","apiUrl":"https://www.simultem-apps.com/api/wiki/v1/articles/salto.reservation-pins","resourceUri":"wiki://salto/reservation-pins","revision":"2026-11-02.1","lastReviewedAt":"2026-11-02"},{"id":"platform.wiki-api","app":"platform","title":"Connect an external AI tool to the wiki API","summary":"Discover apps, search articles and fetch authoritative instructions using a public read-only API.","url":"https://www.simultem-apps.com/wiki/platform#wiki-api","apiUrl":"https://www.simultem-apps.com/api/wiki/v1/articles/platform.wiki-api","resourceUri":"wiki://platform/wiki-api","revision":"2026-11-02.1","lastReviewedAt":"2026-11-02"}]}