NAV
javascript

Introduction

Welcome to the Planly API! You can use our API to schedule posts, upload medias, manage your channels and much more.

Authentication

To authorize, use this code:

fetch('https://app.planly.com/api/...', {
  headers: {
    'Authorization': 'Bearer api_key'
  }
})

Make sure to replace api_key with your API key.

Planly uses API keys to allow access to the API. You can get your Planly API key from Settings > Security.

Planly expects for the API key to be included in all API requests to the server in a header that looks like the following:

Authorization: Bearer api_key

Teams

List Teams

fetch('https://app.planly.com/api/teams/list', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer api_key' },
})

Response:

{
  "data": [
    {
      "id": "874d98cd-34e4-4865-85f4-e9f16172a26f",
      "name": "My team",
      "picture": "...",
      "role": 1,
      "users": 7,
      "channels": 4
    }
  ]
}

This endpoint retrieves all teams that you belong.

HTTP Request

POST https://app.planly.com/api/teams/list

List Channels

fetch('https://app.planly.com/api/channels/list', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer api_key' },
  body: JSON.stringify({
    "team_id": "874d98cd-34e4-4865-85f4-e9f16172a26f"
  })
})

HTTP Request

POST https://app.planly.com/api/channels/list

Parameters

Name Required Description
team_id yes ID of the team to retrieve its channels.

Schedules

List Schedules

fetch('https://app.planly.com/api/v2/schedules/list', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer api_key' },
  body: JSON.stringify({
    "teamId": "1ed3a4fa-ff8f-6166-a14e-6850a91715e8",
    "pagination": {
      "cursor": null,
      "orderBy": ["CreatedAt", "DESC"]
    }
  })
})

Response:

{
  "data": {
    "rows": [
      {
        "id": "1ede989b-3576-69b4-8c32-5662aa0940f5",
        "media": [
          {
            "id": "1ede9882-1d09-6fc1-8c32-20e1401dc7b6",
            "contentUri": "https://cdn.planly.com/media/...",
            "thumbnailUri": "https://cdn.planly.com/media/...",
            "contentType": 1
          }
        ],
        "content": "hello world",
        "status": 1,
        "url": null,
        "publish_on": "2023-05-18T09:00:00.688Z",
        "created_at": "2023-05-03T08:08:34.699515Z"
      }
    ],
    "next": "WyIyMDIzLTA4LTI4VDA4OjI4OjE3LjE3ODE4NloiLCJjNDliNTRlMy0wNWQ1LTRlMjgtOTkwOS01NjU3YTAxNmY5M2EiXQ=="
  }
}

This endpoint retrieves schedules in a specified team. For pagination, include next field returned from response in next request's pagination.cursor field.

HTTP Request

POST https://app.planly.com/api/v2/schedules/list

Parameters

Name Required Description
teamId yes Id of team to retrieve its schedules.
pagination.next Use for pagination

Delete Schedules

fetch('https://app.planly.com/api/v2/schedules/delete', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer api_key' },
  body: JSON.stringify({
    "ids": ["1ede989b-3576-69b4-8c32-5662aa0940f5"]
  })
})

HTTP Request

POST https://app.planly.com/api/v2/schedules/delete

Parameters

Name Required Description
ids yes UUID array with IDs' of schedules to delete.

Create Schedule

fetch('https://app.planly.com/api/v2/schedules/create', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer api_key' },
  body: JSON.stringify({
    "schedules": [
      {
        "channelId": "48e092b8-1d45-4736-acb2-3717218c0f52",
        "publishOn": "2023-11-29T20:00:00.356Z",
        "status": 1,
        "content": "Hello world",
        "media": [
          {
            "options": {},
            "id": "f9560569-3089-49de-9b17-b1f52bc03588"
          }
        ],
        "options": {
          "selfDeclaredMadeForKids": true,
          "notifySubscribers": true,
          "allowEmbedding": true,
          "title": "My YouTube video",
          "categoryId": "28",
          "privacyStatus": "public",
          "firstCommentEnabled": true,
          "firstComment": "My comment"
        }
      },
      {
        "channelId": "c44ed066-a234-4a1d-a1ba-86acca71ae4b",
        "publishOn": "2023-11-29T20:00:00.356Z",
        "status": 1,
        "content": "Hello world",
        "media": [
          {
            "options": {},
            "id": "f9560569-3089-49de-9b17-b1f52bc03588"
          }
        ],
        "options": {
          "postType": 0,
          "firstComment": true,
          "firstCommentContent": "My comment for Instagram"
        }
      }
    ]
  })
})

HTTP Request

POST https://app.planly.com/api/v2/schedules/create

Parameters

Name Required Description
channelId yes
publishOn no Planly will publish schedule at this date and time. If not specified, schedule should be published immediately
status no Status of schedule. 0 for Draft, 1 for Scheduled. Default is 1 (Scheduled)
content no Text content for post
media[] no An array of media (video, image or gif)
options no Social network specific options. (Youtube video category, Instagram post type etc. Detailed docs coming soon)

Media

Overview

To upload media files to Planly you need to first send request to start-upload endpoint with your file size to get uploadUrl. Then upload your files to that url with HTTP PUT request. After your upload finishes, call finish-upload endpoint.

Start Upload

fetch('https://app.planly.com/api/v2/media/start-upload', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer api_key'
  },
  body: JSON.stringify({
    teamId: "1ed3a4fa-ff8f-6166-a14e-6850a91715e8",
    contentLength: 3431948,
    contentType: "video/mp4",
    fileName: "hello.mp4",
  })
})

Response:

{
  "mediaId": "8deb9b93-38ad-448b-ac4b-3bfbc7307214",
  "uploadUrl": "https://planly.s3-accelerate.amazonaws.com/tmp/738536fa54e06b3db16faf726aa6b4913b150e083ceb73669eef4c12ad27dbc7.mp4?X-Amz-Expires=3600&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA46UUZUWCMLGVL6FO%2F20241008%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20241008T081906Z&X-Amz-SignedHeaders=content-length%3Bhost&X-Amz-Signature=d2913f3dae59fd9de669928cd6b01c40c5dd0c042499318e472bfeef1e0273ab", 
  "verb": "PUT",
  "headers": {
    "Content-Type": "video/mp4",
    "Content-Length": "3431948"
  }
}

To initiate the upload process for your media file to Planly, call the start-upload endpoint. The fields teamId and contentLength are mandatory. Additionally, you must provide at least one of the contentType or fileName fields. If both contentType and fileName are provided, only contentType will be honored.

As a response, this endpoint returns a unique mediaId and a pre-signed uploadUrl to which you can upload your file using a PUT request.

Important: The file size (contentLength) will be validated during the upload. For example, if you specify a size of 10MB but attempt to upload a 15MB file, the upload will be rejected.

HTTP Request

POST https://app.planly.com/api/v2/media/start-upload

Parameters

Name Required Description
teamId Yes ID of the team to which the media will be uploaded.
contentLength Yes Size of the file in bytes.
contentType Yes, if fileName is not provided MIME type of the file (e.g., video/mp4).
fileName Yes, if contentType is not provided Name of the file being uploaded.

Finish Upload

fetch('https://app.planly.com/api/v2/media/finish-upload', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer api_key'
  },
  body: JSON.stringify({
    mediaId: "8deb9b93-38ad-448b-ac4b-3bfbc7307214"
  })
})

Response:

{
  "data": {
    "id": "8deb9b93-38ad-448b-ac4b-3bfbc7307214",
    "note": null,
    "contentType": 0,
    "contentLength": 3431948,
    "thumbnailUri": "https://cdn.planly.com/media/1ed3a4faff8f6166a14e6850a91715e8/B15188655D80028A-thumb.jpg",
    "contentUri": "https://cdn.planly.com/media/1ed3a4faff8f6166a14e6850a91715e8/B15188655D80028A.mp4",
    "labels": [],
    "starred": false,
    "duration": 30150,
    "resolution": {
      "width": 1920,
      "height": 1200
    },
    "width": 1920,
    "height": 1200,
    "createdAt": "2024-10-08T08:19:09.1257662Z",
    "createdBy": {
      "id": "1ed3a4fa-ff8f-615d-a14e-9b251da9cf9a",
      "fullname": "Mister Feature",
      "picture": "https://cdn.planly.com/upp/1E41D8FE08430484.jpg"
    }
  },
  "error": null
}

To complete the upload process for your media file, call the finish-upload endpoint. This step is necessary to confirm that the file was successfully uploaded and to finalize its storage on the server. You must provide the mediaId that was returned in the response of the start-upload request.

As a response, this endpoint returns metadata for the uploaded file, including the file's direct URL, resolution, duration (for videos), and creation details.

HTTP Request

POST https://app.planly.com/api/v2/media/finish-upload

Parameters

Name Required Description
mediaId Yes The unique ID of the media file returned from the start-upload response.

Import Media from URL

fetch('https://app.planly.com/api/media/import', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer api_key'
  },
  body: JSON.stringify({
    team_id: "1ed3a4fa-ff8f-6166-a14e-6850a91715e8",
    link: "https://http.cat/200.jpg",
    name: "Awesome cat photo",
  })
})

The response is identical to /media/upload

To import media from URL to your team use this endpoint. Supported media content types are video/mp4, image/png, image/jpeg, image/webp.

HTTP Request

POST https://app.planly.com/api/media/import

Parameters

Name Required Description
team_id yes Id of team to import media.
link yes URL of remote media file.
name no Description of media.

List Media

fetch('https://app.planly.com/api/media/list', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer api_key' },
  body: JSON.stringify({
    "team_id": "1ed3a4fa-ff8f-6166-a14e-6850a91715e8",
    "cursor": null
  })
})

Response:

{
  "data": {
    "medias": [
      {
        "id": "1ede9882-1d09-6fc1-8c32-20e1401dc7b6",
        "note": "",
        "content_type": 1,
        "content_length": 200117,
        "thumbnail_uri": "...",
        "content_uri": "...",
        "labels": [],
        "starred": false,
        "duration": 0,
        "resolution": {
          "width": 1412,
          "height": 958
        },
        "created_at": "2023-05-03T07:57:21.646549Z",
        "created_by": {
          "id": "1ed3a4fa-ff8f-615d-a14e-9b251da9cf9a",
          "fullname": "John Doe",
          "picture": "..."
        },
        "usage": 0
      }
    ],
    "cursor": [
      "1ed9cb26-c8e0-6b53-a4ea-721f892988ee"
    ]
  }
}

This endpoint retrieves medias in a specified team.

HTTP Request

POST https://app.planly.com/api/media/list

Parameters

Name Required Description
team_id yes Id of team to retrieve its medias.
cursor Use for pagination

Delete Media

fetch('https://app.planly.com/api/media/delete', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer api_key' },
  body: JSON.stringify({
    "ids": ["1ede9882-1d09-6fc1-8c32-20e1401dc7b6"]
  })
})

HTTP Request

POST https://app.planly.com/api/media/delete

Parameters

Name Required Description
ids yes UUID array with IDs' of medias to delete.

Artificial Intelligence

Get Available Credits

fetch('https://app.planly.com/api/v2/ai/credits?teamId=874d98cd-34e4-4865-85f4-e9f16172a26f', {
  method: 'GET',
  headers: { 'Authorization': 'Bearer api_key' }
})

Response:

{
  "data": 252
}

Get available AI credits left in a team.

HTTP Request

GET https://app.planly.com/api/v2/ai/credits

Query Parameters

Name Required Description
teamId yes Id of team

Complete Prompt

fetch('https://app.planly.com/api/v2/ai/complete', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer api_key' },
  body: JSON.stringify({
    teamId: "874d98cd-34e4-4865-85f4-e9f16172a26f",
    prompt: "Who is the first president of USA?",
    n: 1
  })
})

Response:

{
  "data": {
    "id": "cmpl-7CUN5FhBapPkwAFRtKNhszvT9fxow",
    "choices": [
      {
        "text": "The first president of the United States was George Washington."
      }
    ]
  }
}

Complete text prompt.

HTTP Request

POST https://app.planly.com/api/v2/ai/complete

Parameters

Name Required Description
teamId yes Id of team
prompt yes Prompt as a text
n yes How many results to generate