Features
Core Groups
Last updated July 2, 2026
Summary
Core Groups (GroupV1) are taxonomy accounts that organize Collections, Assets, and other groups into higher-level sets — for example a brand umbrella that contains multiple collections, or a curated directory of standalone assets.
- Groups store their own name and URI, like collections
- A group can directly contain up to 256 collections, child groups, parent-group links, or assets per vector
- Collections and assets added to a group receive a Groups plugin listing their parent group addresses
Jump to: Create a group · Manage membership · Fetch groups
Collections vs Groups
Collections and groups solve different problems: collections manage member NFTs, while groups provide higher-level taxonomy across collections, assets, and child groups.
| Collection | Group | |
|---|---|---|
| Purpose | Shared metadata and plugins for a series of NFTs | Taxonomy / directory over collections, assets, and groups |
| Owns user NFTs | Yes — assets reference the collection | No — assets remain in their collection (if any) |
| Typical question | “Which series is this NFT from?” | “Which brand, season, or directory includes this collection?” |
| On-chain membership | Asset updateAuthority points at the collection | Member listed in group.collections, group.assets, or group.groups |
Use a Collection when you need collection-wide royalties, freeze rules, or shared artwork for a mint series. Use a Group when you need to organize multiple collections or standalone assets under one label without changing how those assets are minted.
GroupV1 account
A GroupV1 account stores:
| Field | Description |
|---|---|
updateAuthority | Authority that can update the group and change membership |
name | Display name |
uri | Off-chain JSON metadata URI |
collections | Collections that are direct children of this group |
groups | Child groups contained by this group |
parentGroups | Parent groups that contain this group |
assets | Assets that are direct members of this group |
On-chain limits (from mpl-core):
- 256 entries max per vector (
collections,groups,parentGroups,assets) - 8 parent groups max per group (
MAX_GROUP_NESTING_DEPTH)
Groups plugin
When a collection or asset is added to a group, mpl-core ensures a Groups authority-managed plugin exists on that member. The plugin stores the parent group public keys.
Creating groups
Use createGroup / createGroupV1 to deploy a new group account:
1import { generateSigner } from '@metaplex-foundation/umi'
2import { createGroup } from '@metaplex-foundation/mpl-core'
3
4const group = generateSigner(umi)
5
6await createGroup(umi, {
7 group,
8 name: 'My Brand Directory',
9 uri: 'https://example.com/my-brand.json',
10 relationships: [],
11}).sendAndConfirm(umi)
12
13console.log('Group created:', group.publicKey)
You can optionally pass relationships at creation time to link collections, child groups, parent groups, or assets in one transaction. Each relationship entry uses RelationshipKind: Collection, ChildGroup, ParentGroup, or Asset.
Managing group membership
All membership changes are signed by the group update authority unless noted.
| Operation | SDK helper | What it updates |
|---|---|---|
| Add collections | addCollectionsToGroup | Group collections + collection Groups plugin |
| Remove collections | removeCollectionsFromGroup | Both sides |
| Add assets | addAssetsToGroup | Group assets + asset Groups plugin |
| Remove assets | removeAssetsFromGroup | Both sides |
| Add child groups | addGroupsToGroup | Parent groups + child parentGroups |
| Remove child groups | removeGroupsFromGroup | Both sides |
| Update metadata / authority | updateGroup | Group name, URI, update authority |
| Close empty group | closeGroup | Closes the group account |
Add a collection to a group
1import { publicKey } from '@metaplex-foundation/umi'
2import { addCollectionsToGroup } from '@metaplex-foundation/mpl-core'
3
4const group = publicKey('GroupAddress...')
5const collection = publicKey('CollectionAddress...')
6
7await addCollectionsToGroup(umi, {
8 group,
9 authority: umi.identity,
10})
11 .addRemainingAccounts([
12 { pubkey: collection, isSigner: false, isWritable: true },
13 ])
14 .sendAndConfirm(umi)
15
16console.log('Collection added to group')
Add a standalone asset to a group
1import { publicKey } from '@metaplex-foundation/umi'
2import { addAssetsToGroup } from '@metaplex-foundation/mpl-core'
3
4const group = publicKey('GroupAddress...')
5const asset = publicKey('AssetAddress...')
6
7await addAssetsToGroup(umi, {
8 group,
9 authority: umi.identity,
10})
11 .addRemainingAccounts([
12 { pubkey: asset, isSigner: false, isWritable: true },
13 ])
14 .sendAndConfirm(umi)
15
16console.log('Asset added to group')
Nest groups
1import { addGroupsToGroup } from '@metaplex-foundation/mpl-core'
2
3// parentGroup and childGroup are existing GroupV1 accounts
4
5await addGroupsToGroup(umi, {
6 parentGroup: parentGroup.publicKey,
7 groups: [childGroup.publicKey],
8 authority: umi.identity,
9})
10 .addRemainingAccounts([
11 { pubkey: childGroup.publicKey, isSigner: false, isWritable: true },
12 ])
13 .sendAndConfirm(umi)
14
15console.log('Child group nested under parent')
Parent and child vectors stay synchronized: the parent lists the child in groups, and the child lists the parent in parentGroups.
Fetching groups
Use the mpl-core SDK to read on-chain state:
1import { publicKey } from '@metaplex-foundation/umi'
2import { fetchGroupV1 } from '@metaplex-foundation/mpl-core'
3
4const groupAddress = publicKey('GroupAddress...')
5
6const group = await fetchGroupV1(umi, groupAddress)
7
8console.log(group.name)
9console.log(group.collections)
10console.log(group.groups)
11console.log(group.assets)
To list all groups for an update authority, use getGroupV1GpaBuilder (a GPA query — fine for groups, but prefer DAS for large asset scans):
1import { publicKey } from '@metaplex-foundation/umi'
2import { getGroupV1GpaBuilder, Key } from '@metaplex-foundation/mpl-core'
3
4const updateAuthority = publicKey('UpdateAuthorityAddress...')
5
6const groups = await getGroupV1GpaBuilder(umi)
7 .whereField('updateAuthority', updateAuthority)
8 .whereField('key', Key.GroupV1)
9 .getDeserialized()
10
11for (const group of groups) {
12 console.log(group.publicKey, group.name)
13}
Notes
- Groups do not traverse collection membership automatically. Adding a collection to a group does not add that collection’s NFTs to
group.assets. To work with NFTs in a grouped collection, operate on the collection and its assets separately - The Groups plugin blocks burning a group member itself (the collection account or a directly grouped asset) while it still belongs to at least one group. Burning an asset inside a grouped collection does not remove the collection from the group
Glossary
The terms below define the Core Groups concepts used on this page.
| Term | Definition |
|---|---|
| GroupV1 | A Core account that organizes collections, assets, and child groups into a higher-level taxonomy |
| Groups plugin | An authority-managed plugin on a member that stores parent group public keys |
| Direct member | A collection, asset, or child group explicitly listed in a group’s on-chain vectors |
Quick reference
The tables below list the mpl-core program ID and SDK helpers for common group operations.
Program ID
The mpl-core program ID is the same on mainnet and devnet.
| Network | Address |
|---|---|
| Mainnet | CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d |
| Devnet | CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d |
SDK helpers
Use these SDK functions for create, fetch, update, and membership operations.
| Task | Function |
|---|---|
| Create | createGroup |
| Fetch | fetchGroupV1 |
| List by authority | getGroupV1GpaBuilder |
| Update | updateGroup |
| Add collection | addCollectionsToGroup |
| Add asset | addAssetsToGroup |
| Nest group | addGroupsToGroup |
| Close | closeGroup |
FAQ
What is the difference between a Collection and a Group?
A Collection groups Core Assets under shared metadata and collection-level plugins. A Group is a taxonomy container that can reference collections, standalone assets, and other groups. Collections answer “which series does this NFT belong to?” Groups answer “which higher-level set does this collection or asset belong to?”
Can a collection belong to multiple groups?
Yes. When a collection is added to a group, mpl-core writes the parent group address into the collection’s Groups plugin. A collection can list multiple parent groups, up to the on-chain vector limit.
Can groups be nested?
Yes. A group can contain child groups and also list parent groups. Parent/child links are kept in sync on both accounts. A group may belong to up to 8 parent groups.
Do assets inside a grouped collection automatically belong to the group?
No. Group membership is stored on direct members only. Putting a collection in a group adds the collection to group.collections and writes the Groups plugin on the collection. NFTs minted into that collection are not automatically added to group.assets.
Can a standalone asset be a direct member of a group?
Yes. Use addAssetsToGroup to add an asset directly to group.assets without a collection. Collection-managed assets can also be added explicitly when the correct authority signs.
Who can modify group membership?
The group update authority signs add/remove instructions. For collection-managed assets, the collection update authority (or an authorized delegate) can add or remove those assets on the group’s behalf.
