Skip to main content
This page demonstrates how to use custom_json operations for various social interactions on Hive.

What is custom_json?

The custom_json operation allows applications to broadcast custom JSON data to the blockchain. It’s commonly used for social actions like following, reblogging, and community interactions.

CustomJsonOperation Type

interface CustomJsonOperation {
  required_auths: string[]          // Accounts that must sign with active key
  required_posting_auths: string[]  // Accounts that must sign with posting key
  id: string                        // Operation identifier (e.g., 'follow', 'reblog')
  json: string                      // JSON string containing operation data
}

required_auths vs required_posting_auths

  • required_auths: Use when the operation requires active key authority (transfers, financial operations)
  • required_posting_auths: Use when the operation requires posting key authority (social actions like follow, reblog)
For most social operations, use required_posting_auths with an empty required_auths array.

Follow a User

Follow another user on Hive.
import { Transaction, PrivateKey } from 'hive-tx'

async function followUser() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'follow',
    json: JSON.stringify([
      'follow',
      {
        follower: 'your-username',
        following: 'user-to-follow',
        what: ['blog']  // ['blog'] for following, [] for unfollowing
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Follow successful!', result.result.tx_id)
}

Unfollow a User

Unfollow by setting what to an empty array.
import { Transaction, PrivateKey } from 'hive-tx'

async function unfollowUser() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'follow',
    json: JSON.stringify([
      'follow',
      {
        follower: 'your-username',
        following: 'user-to-unfollow',
        what: []  // Empty array means unfollow
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Unfollow successful!', result.result.tx_id)
}

Mute a User

Mute a user to hide their content from your feed.
import { Transaction, PrivateKey } from 'hive-tx'

async function muteUser() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'follow',
    json: JSON.stringify([
      'follow',
      {
        follower: 'your-username',
        following: 'user-to-mute',
        what: ['ignore']  // 'ignore' means mute
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('User muted!', result.result.tx_id)
}

Unmute a User

import { Transaction, PrivateKey } from 'hive-tx'

async function unmuteUser() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'follow',
    json: JSON.stringify([
      'follow',
      {
        follower: 'your-username',
        following: 'user-to-unmute',
        what: []  // Empty array removes mute
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('User unmuted!', result.result.tx_id)
}

Reblog a Post

Share another user’s post to your blog.
import { Transaction, PrivateKey } from 'hive-tx'

async function reblogPost() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'reblog',
    json: JSON.stringify([
      'reblog',
      {
        account: 'your-username',
        author: 'original-author',
        permlink: 'post-permlink'
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Reblog successful!', result.result.tx_id)
}

Delete Reblog

Remove a reblogged post from your blog.
import { Transaction, PrivateKey } from 'hive-tx'

async function deleteReblog() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'follow',
    json: JSON.stringify([
      'reblog',
      {
        account: 'your-username',
        author: 'original-author',
        permlink: 'post-permlink',
        delete: 'delete'  // Special flag to delete reblog
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Reblog deleted!', result.result.tx_id)
}

Subscribe to Community

Subscribe to a Hive community.
import { Transaction, PrivateKey } from 'hive-tx'

async function subscribeToCommunity() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'community',
    json: JSON.stringify([
      'subscribe',
      {
        community: 'hive-123456'  // Community account name
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Subscribed to community!', result.result.tx_id)
}

Unsubscribe from Community

import { Transaction, PrivateKey } from 'hive-tx'

async function unsubscribeFromCommunity() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'community',
    json: JSON.stringify([
      'unsubscribe',
      {
        community: 'hive-123456'
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Unsubscribed from community!', result.result.tx_id)
}

Pin Community Post

Pin a post in your community (requires admin/moderator role).
import { Transaction, PrivateKey } from 'hive-tx'

async function pinCommunityPost() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'community',
    json: JSON.stringify([
      'pinPost',
      {
        community: 'hive-123456',
        account: 'post-author',
        permlink: 'post-permlink'
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Post pinned!', result.result.tx_id)
}

Unpin Community Post

import { Transaction, PrivateKey } from 'hive-tx'

async function unpinCommunityPost() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'community',
    json: JSON.stringify([
      'unpinPost',
      {
        community: 'hive-123456',
        account: 'post-author',
        permlink: 'post-permlink'
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Post unpinned!', result.result.tx_id)
}

Mute Community Post

Mute a post in your community (moderator action).
import { Transaction, PrivateKey } from 'hive-tx'

async function muteCommunityPost() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'community',
    json: JSON.stringify([
      'mutePost',
      {
        community: 'hive-123456',
        account: 'post-author',
        permlink: 'post-permlink',
        notes: 'Reason for muting'
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Post muted!', result.result.tx_id)
}

Set User Role in Community

Assign a role to a user in your community (requires admin).
import { Transaction, PrivateKey } from 'hive-tx'

async function setUserRole() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'community',
    json: JSON.stringify([
      'setRole',
      {
        community: 'hive-123456',
        account: 'user-account',
        role: 'mod'  // Roles: 'admin', 'mod', 'member', 'guest'
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('User role set!', result.result.tx_id)
}

Update Community Settings

Update your community settings (requires admin).
import { Transaction, PrivateKey } from 'hive-tx'

async function updateCommunitySettings() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'community',
    json: JSON.stringify([
      'updateProps',
      {
        community: 'hive-123456',
        props: {
          title: 'My Community Title',
          about: 'Community description',
          lang: 'en',
          description: 'Longer community description',
          flag_text: 'Rules for the community',
          is_nsfw: false
        }
      }
    ])
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Community updated!', result.result.tx_id)
}

Custom App-Specific JSON

You can create custom operations for your own application.
import { Transaction, PrivateKey } from 'hive-tx'

async function customAppOperation() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: [],
    required_posting_auths: ['your-username'],
    id: 'my-app',  // Your app identifier
    json: JSON.stringify({
      action: 'like',
      target: 'post-id-123',
      metadata: {
        timestamp: Date.now(),
        version: '1.0.0'
      }
    })
  })
  
  const key = PrivateKey.from('your-posting-key')
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Custom operation successful!', result.result.tx_id)
}

Using Active Authority

For operations requiring active key (e.g., financial operations).
import { Transaction, PrivateKey } from 'hive-tx'

async function customJsonWithActiveAuth() {
  const tx = new Transaction()
  
  await tx.addOperation('custom_json', {
    required_auths: ['your-username'],  // Active key required
    required_posting_auths: [],
    id: 'financial-operation',
    json: JSON.stringify({
      action: 'transfer_tokens',
      amount: 100,
      to: 'recipient'
    })
  })
  
  const key = PrivateKey.from('your-active-key')  // Active key, not posting
  tx.sign(key)
  
  const result = await tx.broadcast()
  console.log('Active auth operation successful!', result.result.tx_id)
}

Common custom_json ID Values

  • follow - Following, unfollowing, muting users
  • reblog - Reblogging posts
  • community - Community operations
  • notify - Notification settings
  • rc - Resource credit delegations
  • Custom app IDs for your application

Important Notes

  • Most social operations use posting key (required_posting_auths)
  • Financial operations use active key (required_auths)
  • The json field must be a valid JSON string
  • Community operations require appropriate permissions (admin/mod)
  • Custom app IDs should be unique to avoid conflicts
When developing custom operations, choose a unique id value for your app to avoid conflicts with other applications on the blockchain.

Build docs developers (and LLMs) love