Error: POST accounts/:account_id/videos Ads API

video
media-upload
api

#1

Hello!

We have a problem associating media with account.
We have successfully uploaded media:

twurl -H upload.twitter.com '/1.1/media/upload.json?command=STATUS&media_id=857228996186189824'
{
  "media_id": 857228996186189800,
  "media_id_string": "857228996186189824",
  "size": 41436957,
  "expires_after_secs": 15551902,
  "video": {
    "video_type": "video/mp4"
  },
  "processing_info": {
    "state": "succeeded",
    "progress_percent": 100
  }
}

But when we try to associate media with account we get error:

twurl -X POST -H ads-api.twitter.com '/1/accounts/18ce54h6wox/videos?video_media_id=857228996186189824'
{
  "errors": [
    {
      "code": "INVALID_MEDIA_ID",
      "message": "Media referenced by media_id id was not found."
    }
  ],
  "request": {
    "params": {}
  }
}

Can you help us please!

Thanks in advance!

Regards, Aleksander


#2

@Jancic_A: Thanks for providing these details. On the POST media/upload’s INIT step, did you use the additional_owners parameter?


#3

No, we didn’t.

We already created videos and video cards without sending “additional_owners” in the past (not same account).
With some accounts it works.

Ok. We will try with “additional_owners”.

Regards, Aleksander


#4

We have been experiencing this same issue and we tried with the additional_owners field, but still getting INVALID_MEDIA_ID error code


#5

@jameskupernik: Please provide the series of requests you’re making as well as the responses you’re getting so that we can investigate further. Thanks!


#6

@juanshishido

I work with James, here is the series of requests (this is not the exact formatting of the parameters in the request, just a readable list of what is being passed). The set of requests is the same for both successful and unsuccessful attempts, the only difference is the user performing the request, and the ad account the upload is being added to. In the successful attempts, the user performing the upload (which is the same user specified in ‘additional_owners’) is also the owner of the ad account. In the error case, the user is associated with the ad account as an Admin.

INIT upload
Request
https://upload.twitter.com/1.1/media/upload.json
command=INIT
total_bytes=9596204
mime_type=video%2Fmp4
media_category=amplify_video
additional_owners=145671066

Response
{"media_id":867402349358321664,"media_id_string":"867402349358321664","expires_after_secs":15552000}

APPEND upload
(Omitted, these aren't very interesting)

FINALIZE upload
Request
https://upload.twitter.com/1.1/media/upload.json
command=FINALIZE
media_id=867402349358321664

Response
{"media_id":867402349358321664,"media_id_string":"867402349358321664","size":9596204,"expires_after_secs":15552000,"processing_info":{"state":"pending","check_after_secs":5}}

STATUS checks
Request
https://upload.twitter.com/1.1/media/upload.json?command=STATUS&media_id=867402349358321664

Response
{"media_id":867402349358321664,"media_id_string":"867402349358321664","processing_info":{"state":"in_progress","check_after_secs":5,"progress_percent":57}}

... wait until processing_info.state = 'succeeded'

https://upload.twitter.com/1.1/media/upload.json?command=STATUS&media_id=867402349358321664
{"media_id":867402349358321664,"media_id_string":"867402349358321664","size":9596204,"expires_after_secs":15551996,"video":{"video_type":"video\/mp4"},"processing_info":{"state":"succeeded","progress_percent":100}}

Attach Media to Ad Account
Request
https://ads-api.twitter.com/1/accounts/18ce54htjjm/videos
video_media_id=867402349358321664
title=A%20test%20twitter%20ad
description=A%20test%20twitter%20ad

Response (if successful)
{"data_type":"video","data":{"id":"13_867402349358321664"},"request":{"params":{"video_media_id":867402349358321664,"title":"A test twitter ad","description":"A test twitter ad","account_id":"18ce54htjjm"}}}

Response (if error)
{"errors":[{"code":"INVALID_MEDIA_ID","message":"Media referenced by media_id id wa
s not found."}],"request":{"params":{}}}

#7

Thanks, @hank_zill! These details are very helpful.

Let me confirm that I understand the two paths:

  • success: user A upload the video (this is the authenticating user) and can associate that video with their ads account (they are the full promotable user on the ads account)
    • note: in this scenario, it’s not necessary to specify user A as an additional owner (user A is the original owner)
  • failure: user A uploads the video, but user B cannot associate the video with their ads account

Is this correct?

For the failure case, because it wasn’t explicitly mentioned, is user B added as an additional_owner?


#8

In both cases, the same user is both uploading the video and associating the video with the ad account.

So in the success case, User A is the authenticating user, performs the upload, and associates the upload with their ad account.
In the failure case, User B is the authenticating user, performs the upload (with their user ID specified as additional_owners), and attempts to associate the freshly uploaded video with an ad account that they are an Admin (their company’s ad account, for example)


#9

Good clarification, @hank_zill. In this example, the ads account is actually owned by a different user (user C, for example), correct? If so, what happens when you add that user as an additional_owner?


#10

That is correct. The ad account we’re trying to add the media to is owned by a different user.

Given that all we have at this point in the process is the uploading user’s User ID and the Ad Account ID they are trying to add the video to, is there a way to use your API to find out the User ID of the Ad Account owner in order to set the additional_owner to that ID?


#11

You should know the @handle for that ads account’s owner. With that information, you can use the GET users/show endpoint, as follows:

$ twurl -H api.twitter.com "/1.1/users/show.json?screen_name=apimctestface"
{
  "id": 756201191646691328,
  "id_str": "756201191646691328",
  "name": "API McTestface",
  "screen_name": "apimctestface",
  "location": "San Francisco, CA",
  "profile_location": {
    "id": "5a110d312052166f",
    "url": "https://api.twitter.com/1.1/geo/id/5a110d312052166f.json",
    "place_type": "unknown",
    "name": "San Francisco, CA",
    "full_name": "San Francisco, CA",
    "country_code": "",
    "country": "",
    "contained_within": [],
    "bounding_box": null,
    "attributes": {}
  },
  "description": "Into testing and APIs",
  "url": null,
  "entities": {
    "description": {
      "urls": []
    }
  },
  "protected": false,
  "followers_count": 2,
  "friends_count": 0,
  "listed_count": 0,
  "created_at": "Thu Jul 21 18:56:28 +0000 2016",
  "favourites_count": 0,
  "utc_offset": null,
  "time_zone": null,
  "geo_enabled": false,
  "verified": false,
  "statuses_count": 3,
  "lang": "en",
  ...,
  "contributors_enabled": false,
  "is_translator": false,
  "is_translation_enabled": false,
  "profile_background_color": "000000",
  "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
  "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
  "profile_background_tile": false,
  "profile_image_url": "http://pbs.twimg.com/profile_images/756348317458509825/DTKcRCpS_normal.jpg",
  "profile_image_url_https": "https://pbs.twimg.com/profile_images/756348317458509825/DTKcRCpS_normal.jpg",
  "profile_banner_url": "https://pbs.twimg.com/profile_banners/756201191646691328/1469162431",
  "profile_link_color": "000000",
  "profile_sidebar_border_color": "000000",
  "profile_sidebar_fill_color": "000000",
  "profile_text_color": "000000",
  "profile_use_background_image": false,
  "has_extended_profile": true,
  "default_profile": false,
  "default_profile_image": false,
  "following": true,
  "follow_request_sent": false,
  "notifications": false,
  "translator_type": "none"
}

The id_str is the user ID.


#12

With a self-service integration like this, we don’t know anything about the ad accounts that the connecting user has access to.

Any thoughts on possible solutions to this?

Thanks


#13

Makes sense.

What you do know is the account ID.

$ twurl -H ads-api.twitter.com "/1/accounts"
{
  "request": {
    "params": {}
  },
  "data": [
    ...,
    {
      "name": "API McTestface",
      "business_name": null,
      "timezone": "America/Los_Angeles",
      "timezone_switch_at": "2016-07-21T07:00:00Z",
      "id": "18ce54d4x5t",
      "created_at": "2016-07-21T22:42:09Z",
      "salt": "54cb7b5a34183f77d82dd6d0f4329691",
      "updated_at": "2017-05-24T21:22:54Z",
      "business_id": null,
      "approval_status": "ACCEPTED",
      "deleted": false
    }
  ],
  "data_type": "account",
  "total_count": 6,
  "next_cursor": null
}

I—the authenticating user—have access to six ads accounts. Above, I’m only showing 18ce54d4x5t. With this information, you can make the following request:

$ twurl -H ads-api.twitter.com "/1/accounts/18ce54d4x5t/promotable_users"
{
  "request": {
    "params": {
      "account_id": "18ce54d4x5t"
    }
  },
  "data": [
    {
      "user_id": "756201191646691328",
      "id": "l310s",
      "account_id": "18ce54d4x5t",
      "created_at": "2016-07-21T22:42:09Z",
      "updated_at": "2016-07-21T22:42:09Z",
      "deleted": false,
      "promotable_user_type": "FULL"
    },
    {
      "user_id": {user_id},
      "id": "ozor5",
      "account_id": "18ce54d4x5t",
      "created_at": "2017-03-10T17:51:24Z",
      "updated_at": "2017-03-10T17:51:24Z",
      "deleted": false,
      "promotable_user_type": "RETWEETS_ONLY"
    }
  ],
  "data_type": "promotable_user",
  "total_count": 2,
  "next_cursor": null
}

Look for the FULL promotable user. The user_id is what you’re looking for.

Hope this helps!


#14

Perfect! I already had the ad account ID, so I just needed to query the promotable_users to find the FULL one (I assume if there is more than one that they will be interchangeable, I’m just grabbing the first one I see). Setting the additional_owners to that user_id fixed the issue…


#15

There is only ever one FULL promotable user per ads account.

Thanks for letting us know this was helpful!


#16

Will there ever be an ad account without a FULL promotable user? Or is it guaranteed that all ad accounts have exactly one?


#17

@hank_zill: Good follow up. There will always be exactly one FULL promotable user.