> For the complete documentation index, see [llms.txt](https://docs.pandium.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pandium.com/getting-started/pandium-integration-tutorial/pokemon-of-the-day-part-2/update-the-pokemonsync-flow.md).

# Update the pokemonSync flow

Update the pokemonSync flow so each tenant’s daily Slack message uses the selected Pokémon type and Slack user from dynamic configs, while still advancing IDs via tenant metadata.

You have access to the newly created slack\_user and pokemon\_type configs. Let's update pokemonSync to make use of them.

The Pokémon Trainer Academy needs the new `pokemonSync` to do the following:

* The Pokémon of the day must always be of the type selected in the tenant's connection settings.
* The Slack message should only be sent to the Slack user specified in the tenant's connection settings.

To do this we will need to:

* [ ] Fetch Pokémon Type selected in the config.
* [ ] Select the Pokémon of the Day from the Pokémon within that type.
* [ ] Fetch the Pokémon of the Day.
* [ ] Send a Slack message about that Pokémon to the Slack user selected in the config.

You just saved a Pokémon type and a Slack user in your tenant's connection settings, and the CLI passes those selections to local runs.

1. Run `pandium local build && pandium local run <tenant-id>`. The tenant configs at the top of the logs should now hold your selections:

```
[2026-09-08 11:30:26:118] [index] INFO: Tenant configs: {"pokemon_type":"rock","slack_user":"<YOUR-SLACK-MEMBER-ID>"}
```

2. Fetch the selected Pokémon type by doing the following:
   * [ ] In `pokemonSync` read `pokemon_type` and `slack_user` from `pandium.config`. Since a config may be missing, throw an error if either one is not set.
   * [ ] Pass the selected type to the `pokeClient.getTypeByName`method to fetch it.
   * [ ] Log out the results of that fetch.

The pokemonSync.ts file should look something like this:

```typescript
import log4js from 'log4js'
import Pokedex from 'pokedex-promise-v2'
import { WebClient } from '@slack/web-api'
import { pokemonToSlackMessage } from '../transformations.js'
import { Pandium } from '../lib.js'

const logger = log4js.getLogger('pokemonSync')

export const pokemonSync = async (
    pokeClient: Pokedex,
    slackClient: WebClient,
    pandium: Pandium
) => {
    logger.info('------------------------POKEMON SYNC------------------------')

    const { pokemon_type: selectedType, slack_user: slackUser } = pandium.config
    if (!selectedType || !slackUser) {
        throw new Error('A Pokémon type and Slack user must be selected in the connection settings')
    }

    const pokemonType = await pokeClient.getTypeByName(selectedType)
    logger.info(pokemonType)

    const lastPokemonId = Number(pandium.metadata()?.last_pokemon_id) || 0
    logger.info(`The last Pokémon of the day was #${lastPokemonId}`)

    const nextPokemonId = lastPokemonId + 1
    const pokemonOfTheDay = await pokeClient.getPokemonByName(nextPokemonId)

    const slackMemberIds = ['<YOUR-SLACK-MEMBER-ID>']

    for (const slackID of slackMemberIds) {
        const slackMessage = pokemonToSlackMessage(pokemonOfTheDay, slackID)
        await slackClient.chat.postMessage(slackMessage)
    }

    return { last_pokemon_id: nextPokemonId }
}
```

3. Run `pandium local build && pandium local run <tenant-id>`.

You should get a Pokémon Slack message, but we're more interested in examining the logs; they should look something like this:

```
[2026-09-08 11:34:51:902] [index] INFO: This run is in mode: normal
[2026-09-08 11:34:51:903] [index] INFO: Tenant configs: {"pokemon_type":"rock","slack_user":"<YOUR-SLACK-MEMBER-ID>"}
[2026-09-08 11:34:51:903] [pokemonSync] INFO: ------------------------POKEMON SYNC------------------------
[2026-09-08 11:34:52:377] [pokemonSync] INFO: {
  damage_relations: {... various damage relations properties of the rock Pokémon type}
  ... more properties of the rock Pokémon type
}
[2026-09-08 11:34:52:378] [pokemonSync] INFO: The last Pokémon of the day was #3
[2026-09-08 11:34:53:015] [lib] INFO: updating metadata with {"last_pokemon_id":4}
{"last_pokemon_id":4}
```

You can remove the `logger.info(pokemonType)`

You can learn about the shape of a Pokémon type by examining the one you just logged out or reviewing [the PokéAPI docs for the `type` endpoint](https://pokeapi.co/docs/v2#types).

You'll see that each Pokémon type has the property `pokemon`; it's an array of the type's Pokémon. We should select the Pokémon of the day from that list!

Each member of the `pokemon` array has the following shape:

```json
{
  "slot": 1,
  "pokemon": {
    "name": "sandshrew",
    "url": "https://pokeapi.co/api/v2/pokemon/27/"
  }
}
```

4. Change how `nextPokemonId` is defined; it should be the ID of the first member of the fetched type's `pokemon` array whose ID is greater than `lastPokemonId`.

Here is one way you could do this:

```typescript
import log4js from 'log4js'
import Pokedex from 'pokedex-promise-v2'
import { WebClient } from '@slack/web-api'
import { pokemonToSlackMessage } from '../transformations.js'
import { Pandium } from '../lib.js'

const logger = log4js.getLogger('pokemonSync')

export const pokemonSync = async (
    pokeClient: Pokedex,
    slackClient: WebClient,
    pandium: Pandium
) => {
    logger.info('------------------------POKEMON SYNC------------------------')

    const { pokemon_type: selectedType, slack_user: slackUser } = pandium.config
    if (!selectedType || !slackUser) {
        throw new Error('A Pokémon type and Slack user must be selected in the connection settings')
    }

    const pokemonType = await pokeClient.getTypeByName(selectedType)
    const pokemonOptions = pokemonType.pokemon

    const lastPokemonId = Number(pandium.metadata()?.last_pokemon_id) || 0
    logger.info(`The last Pokémon of the day was #${lastPokemonId}`)

    let nextPokemonId: number | undefined
    for (const pokemon of pokemonOptions) {
        const pokemonId = Number(pokemon.pokemon.url.split('/').slice(-2, -1)[0])
        if (pokemonId <= lastPokemonId) continue
        nextPokemonId = pokemonId
        break
    }
    if (!nextPokemonId) return { last_pokemon_id: lastPokemonId }

    const pokemonOfTheDay = await pokeClient.getPokemonByName(nextPokemonId)

    const slackMemberIds = ['<YOUR-SLACK-MEMBER-ID>']

    for (const slackID of slackMemberIds) {
        const slackMessage = pokemonToSlackMessage(pokemonOfTheDay, slackID)
        await slackClient.chat.postMessage(slackMessage)
    }

    return { last_pokemon_id: nextPokemonId }
}
```

5. Run `pandium local build && pandium local run <tenant-id>`.

This time the Pokémon in your Slack message should be of the type you selected, and the ID in the standard out will have jumped ahead to it. Because local runs don't update the tenant's metadata, running again will send the same Pokémon; you'll see the ID advance when you run on Pandium.

6. Now adjust pokemonSync to use the slack\_user config
   * [ ] Remove the array of hard coded `slackMemberIds`.
   * [ ] Instead of sending a Slack message for every member in that array just pass `slackUser` to `pokemonToSlackMessage`, and only call `slackClient.chat.postMessage` for that one `slackMessage.`

Your pokemonSync.ts could look like this now:

```typescript
import log4js from 'log4js'
import Pokedex from 'pokedex-promise-v2'
import { WebClient } from '@slack/web-api'
import { pokemonToSlackMessage } from '../transformations.js'
import { Pandium } from '../lib.js'

const logger = log4js.getLogger('pokemonSync')

export const pokemonSync = async (
    pokeClient: Pokedex,
    slackClient: WebClient,
    pandium: Pandium
) => {
    logger.info('------------------------POKEMON SYNC------------------------')

    const { pokemon_type: selectedType, slack_user: slackUser } = pandium.config
    if (!selectedType || !slackUser) {
        throw new Error('A Pokémon type and Slack user must be selected in the connection settings')
    }

    const pokemonType = await pokeClient.getTypeByName(selectedType)
    const pokemonOptions = pokemonType.pokemon

    const lastPokemonId = Number(pandium.metadata()?.last_pokemon_id) || 0
    logger.info(`The last Pokémon of the day was #${lastPokemonId}`)

    let nextPokemonId: number | undefined
    for (const pokemon of pokemonOptions) {
        const pokemonId = Number(pokemon.pokemon.url.split('/').slice(-2, -1)[0])
        if (pokemonId <= lastPokemonId) continue
        nextPokemonId = pokemonId
        break
    }
    if (!nextPokemonId) return { last_pokemon_id: lastPokemonId }

    const pokemonOfTheDay = await pokeClient.getPokemonByName(nextPokemonId)

    const slackMessage = pokemonToSlackMessage(pokemonOfTheDay, slackUser)
    await slackClient.chat.postMessage(slackMessage)

    return { last_pokemon_id: nextPokemonId }
}
```

7. Run `pandium local build && pandium local run <tenant-id>`.

Once again, this run's results should look the same as the last run's. This shows that accessing the Slack user's ID from the tenant's configs, instead of a hardcoded list, does not interfere with the rest of the flow's functionality.

Your pokemonSync.ts should match [this one](https://github.com/pandium/sample_integrations/blob/master/POKEMON_OF_THE_DAY/src/processLogic/pokemonSync.ts). In fact your integration files should match all the ones in [this repository](https://github.com/pandium/sample_integrations/tree/master/POKEMON_OF_THE_DAY).

The final step is to see what this all looks like when it is run on Pandium!


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.pandium.com/getting-started/pandium-integration-tutorial/pokemon-of-the-day-part-2/update-the-pokemonsync-flow.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
