> ## Documentation Index
> Fetch the complete documentation index at: https://docs.connectadesk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Token security

> Best practices for Connecta DESK API tokens: minimum permissions, expiration date, allowed IP list, rotation and what to do if a token leaks.

An API token gives access to the whole company's data, within the permissions checked on it. There
is no second factor and no email confirmation. Anyone who has the token can use the API on the
company's behalf.

This page gathers the practices that limit the damage if a token leaks or is misused. The best time
to decide a token's permissions is when you create it.

## One token per integration

<Warning>
  The most common mistake is creating a "general" token, with every permission, and using the same
  one in several systems. If it leaks, you do not know which system it leaked from, and revoking it
  stops every integration at once.
</Warning>

With one token for each system that uses the API, both problems go away. The name and `lastUsedAt`
show which system uses each token, and revoking one of them affects only that system.

<Columns cols={2}>
  <Card title="Name it after the system that uses it" icon="tag">
    Use names like `ERP contact sync` or `BI nightly reports`. A name like "token 1" does not
    help when someone needs to decide whether it can be revoked.
  </Card>

  <Card title="Minimum scope" icon="shield-check">
    Check only what the integration uses today. Widening the permissions later takes about 30
    seconds in the panel. Fixing the damage from a token with too many permissions takes a lot more
    work.
  </Card>
</Columns>

## What deserves extra attention

Some permissions give more power than others. Two call for special care:

<AccordionGroup>
  <Accordion title="Writing on users amounts to administrative power" icon="user-cog">
    With `users: ["POST"]`, the token can invite people to the company. With `users: ["PUT"]`, it
    can change the profile of anyone already in it, including promoting someone to administrator.
    An administrator, in turn, can create new tokens.

    Give these permissions only to HR or access provisioning integrations that truly need them. If
    the routine only needs to list users, give it just `GET`.
  </Accordion>

  <Accordion title="DELETE has no undo" icon="trash-2">
    Deletions through the API do not ask for confirmation. If a faulty sync calls
    `DELETE /contacts/{id}` over and over, there is no way to undo it.

    If the integration needs to delete data, keep that part in a separate routine, with a second
    token and its own log.
  </Accordion>
</AccordionGroup>

## Expiry and allowlist

<Steps>
  <Step title="Set an expiry whenever it makes sense">
    Tokens for a project with a planned end, a vendor trial or a proof of concept should be created
    with an expiration date from the start. A token with no expiry keeps working years after the
    project ends.

    Write the expiration date down in the integration's documentation. An expired token gets the
    same `401` as any invalid token, and without that note it is hard to find out why the
    integration stopped.
  </Step>

  <Step title="Restrict the IP when there is a fixed IP">
    With the allowed IP list (allowlist) filled in, the token only works on calls coming from those
    addresses. Even if it leaks, it cannot be used from anywhere else.

    The list accepts IPv4 addresses (`200.150.10.20`) and CIDR ranges (`191.30.0.0/16`), with up to
    50 entries.

    <Warning>
      Before restricting, confirm the real **outbound** IP of the system that uses the token. Cloud
      services often go out through an address different from the one shown in the provider's
      panel, and a wrong list makes the integration stop right away.
    </Warning>
  </Step>

  <Step title="Rotate periodically">
    **Rotating** generates a new value for the token and keeps the name, permissions and allowlist.
    The integration's configuration stays the same and only the key changes. The old value stops
    working right away, so agree on the time of the switch with whoever runs the system that uses
    the token.
  </Step>
</Steps>

## Where the key may live

<Columns cols={2}>
  <Card title="Allowed" icon="circle-check">
    Environment variable, secrets vault (Vault, AWS Secrets Manager, Doppler), encrypted server
    configuration.
  </Card>

  <Card title="Not allowed" icon="circle-x">
    Repository, front-end, mobile app, spreadsheet, chat message, support ticket,
    screenshot.
  </Card>
</Columns>

<Warning>
  Never call the API directly from the browser or from a mobile app. Anything that reaches the
  user's device can be read by them, and the key would be exposed. Make the calls through a service
  of your own, which keeps the token and lets the app do only what that user is allowed to do.
</Warning>

Be careful with logs too. Recording the whole request in debug mode often writes the
`Authorization` header along with it. Hide that field before saving the log.

## If a key has leaked

<Steps>
  <Step title="Revoke or rotate now" icon="ban">
    Do it in the panel, under **Settings → Integrations → API**. Revocation takes effect right away,
    with no grace period.

    Rotate if the integration needs to keep running. Revoke if it can stop.
  </Step>

  <Step title="See what that token could reach" icon="search">
    Open the token and check its permissions. They show exactly what could have been done with it.
    A token with `reports: ["GET"]`, for example, gave access to reports but could not change any
    contact.

    The `lastUsedAt` shows when it was last used.
  </Step>

  <Step title="Fix the source" icon="wrench">
    If you only rotate, without finding out how the key leaked, the problem may happen again. Check
    repositories, logs, screenshots and credentials shared in chat, and fix the cause before handing
    out the new key.
  </Step>
</Steps>

## Periodic review

Once a quarter, open the token list and check each one:

<Check>
  Is there still an integration using this token? The `lastUsedAt` shows it.
</Check>

<Check>
  Do the permissions still match what the integration does today, or is there one left over from
  an old version?
</Check>

<Check>
  Does the expiration date make sense, or is it a token with no expiry from a project that has
  already ended?
</Check>

<Check>
  Does the person who created the token still work at the company? The panel shows who created it
  and who edited it last.
</Check>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.