API Status Get API Key

Create Instagram Post With User Tags

Try in Explorer

User tags let you tag Instagram accounts at a specific point on an image. They are attached per image, on the asset's metadata.userTags field - not on the Instagram post metadata - so the same approach works for Instagram posts and stories.

Each tag is a UserTagInput with a handle and an x/y position. The coordinates are normalized decimal floats between 0.0 and 1.0, representing the percentage distance from the left edge (x) and the top edge (y) of the image. So { x: 0.5, y: 0.5 } is the center of the image, and { x: 0.0, y: 0.0 } is the top-left corner.

Common pitfall: pass x and y as numbers, not strings, and as normalized 0.0-1.0 values - not raw pixel coordinates. Sending pixel values (e.g. x: 540 on a 1080px-wide image) or strings causes Instagram's Graph API to reject the post with an error like Failed to create media container for instagram: (#100) Param user_tags[0]['x'] must be a number less than or equal to 1. To convert a pixel position, divide by the image's dimension: x = pixelX / imageWidth, y = pixelY / imageHeight.

Note that metadata.altText is required whenever you provide image metadata, so it's included alongside userTags below.

mutation CreateInstagramPostWithUserTags {
  createPost(
    input: {
      text: "Your post caption goes here"
      channelId: "your_instagram_channel_id"
      schedulingType: automatic
      mode: addToQueue
      assets: [
        {
          image: {
            url: "https://images.unsplash.com/photo-1742850541164-8eb59ecb3282?q=80&w=3388&auto=format&fit=crop"
            metadata: {
              altText: "Describe the image for accessibility"
              userTags: [
                { handle: "first_account_handle", x: 0.5, y: 0.7 }
                { handle: "second_account_handle", x: 0.5, y: 0.95 }
              ]
            }
          }
        }
      ]
      metadata: { instagram: { type: post, shouldShareToFeed: true } }
    }
  ) {
    ... on PostActionSuccess {
      post {
        id
        text
        assets {
          id
          mimeType
        }
      }
    }
    ... on MutationError {
      message
    }
  }
}
curl -X POST 'https://api.buffer.com' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{"query": "mutation CreateInstagramPostWithUserTags {\n  createPost(\n    input: {\n      text: \"Your post caption goes here\"\n      channelId: \"your_instagram_channel_id\"\n      schedulingType: automatic\n      mode: addToQueue\n      assets: [\n        {\n          image: {\n            url: \"https://images.unsplash.com/photo-1742850541164-8eb59ecb3282?q=80&w=3388&auto=format&fit=crop\"\n            metadata: {\n              altText: \"Describe the image for accessibility\"\n              userTags: [\n                { handle: \"first_account_handle\", x: 0.5, y: 0.7 }\n                { handle: \"second_account_handle\", x: 0.5, y: 0.95 }\n              ]\n            }\n          }\n        }\n      ]\n      metadata: { instagram: { type: post, shouldShareToFeed: true } }\n    }\n  ) {\n    ... on PostActionSuccess {\n      post {\n        id\n        text\n        assets {\n          id\n          mimeType\n        }\n      }\n    }\n    ... on MutationError {\n      message\n    }\n  }\n}"}'
async function createInstagramPostWithUserTags() {
  const response = await fetch('https://api.buffer.com', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_API_KEY',
    },
    body: JSON.stringify({
      query: `
      mutation CreateInstagramPostWithUserTags {
        createPost(
          input: {
            text: "Your post caption goes here"
            channelId: "your_instagram_channel_id"
            schedulingType: automatic
            mode: addToQueue
            assets: [
              {
                image: {
                  url: "https://images.unsplash.com/photo-1742850541164-8eb59ecb3282?q=80&w=3388&auto=format&fit=crop"
                  metadata: {
                    altText: "Describe the image for accessibility"
                    userTags: [
                      { handle: "first_account_handle", x: 0.5, y: 0.7 }
                      { handle: "second_account_handle", x: 0.5, y: 0.95 }
                    ]
                  }
                }
              }
            ]
            metadata: { instagram: { type: post, shouldShareToFeed: true } }
          }
        ) {
          ... on PostActionSuccess {
            post {
              id
              text
              assets {
                id
                mimeType
              }
            }
          }
          ... on MutationError {
            message
          }
        }
      }
      `,
    }),
  });

  const data = await response.json();
  console.log(JSON.stringify(data, null, 2));
}

createInstagramPostWithUserTags();
import requests

query = """
mutation CreateInstagramPostWithUserTags {
  createPost(
    input: {
      text: "Your post caption goes here"
      channelId: "your_instagram_channel_id"
      schedulingType: automatic
      mode: addToQueue
      assets: [
        {
          image: {
            url: "https://images.unsplash.com/photo-1742850541164-8eb59ecb3282?q=80&w=3388&auto=format&fit=crop"
            metadata: {
              altText: "Describe the image for accessibility"
              userTags: [
                { handle: "first_account_handle", x: 0.5, y: 0.7 }
                { handle: "second_account_handle", x: 0.5, y: 0.95 }
              ]
            }
          }
        }
      ]
      metadata: { instagram: { type: post, shouldShareToFeed: true } }
    }
  ) {
    ... on PostActionSuccess {
      post {
        id
        text
        assets {
          id
          mimeType
        }
      }
    }
    ... on MutationError {
      message
    }
  }
}
"""

response = requests.post(
    "https://api.buffer.com",
    headers={
        "Content-Type": "application/json",
        "Authorization": "Bearer YOUR_API_KEY",
    },
    json={
        "query": query,
    },
)

data = response.json()
print(data)
<?php

$query = '
mutation CreateInstagramPostWithUserTags {
  createPost(
    input: {
      text: "Your post caption goes here"
      channelId: "your_instagram_channel_id"
      schedulingType: automatic
      mode: addToQueue
      assets: [
        {
          image: {
            url: "https://images.unsplash.com/photo-1742850541164-8eb59ecb3282?q=80&w=3388&auto=format&fit=crop"
            metadata: {
              altText: "Describe the image for accessibility"
              userTags: [
                { handle: "first_account_handle", x: 0.5, y: 0.7 }
                { handle: "second_account_handle", x: 0.5, y: 0.95 }
              ]
            }
          }
        }
      ]
      metadata: { instagram: { type: post, shouldShareToFeed: true } }
    }
  ) {
    ... on PostActionSuccess {
      post {
        id
        text
        assets {
          id
          mimeType
        }
      }
    }
    ... on MutationError {
      message
    }
  }
}
';

$payload = [
    'query' => $query,
];

$ch = curl_init('https://api.buffer.com');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_API_KEY',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
print_r($data);

The x/y validation rules are enforced by Instagram, so the same constraints apply whether you tag one account or many. See the UserTag reference for the field definitions, and Create an Image Post for the basics of attaching images.