WebService::Pinterest - Pinterest API client


    use WebService::Pinterest;

    $pinterest = WebService::Pinterest->new( access_token => $access_token );

    $r1 = $pinterest->fetch('me');
    $r2 = $pinterest->fetch('my/pins');
    $r3 = $pinterest->fetch('board/pins', {board => $board});

    $r4 = $pinterest->create('board', board => 'nobody/board');
    $r5 = $pinterest->create(
        board     => 'nobody/board',
        note      => 'Nothing at nowhere',
        image_url => '',
        link      => '',

    $r6 = $pinterest->edit('pin', {pin => 9999999, note => $new_note, link => $new_link});


This module implements a client for the Pinterest API documented at:

This code is in alpha state. Its interface may change in the next releases.

Pinterest offers a RESTful API that gives access to user's Pinterest data, like their boards, pins, followers and more.

WebService::Pinterest gives you an easy way to access most of the official Pinterest API capabilities from a Perl program.


Pinterest API endpoints are tuples with HTTP method and endpoint path.

The HTTP methods for the current API endpoints are:


Examples of current endpoints (methods and paths) are:

    GET   /v1/me/
    GET   /v1/me/likes/
    GET   /v1/users/:user
    POST  /v1/boards/
    GET   /v1/boards/:board/pins/
    PATCH /v1/boards/:board/

Each of the documented endpoints can be invoked with the help of the call() method. For example,

    $pinterest->call(GET => '/v1/me/');
    $pinterest->call(GET => '/v1/me/likes/', fields => 'id,note,board,link,url,counts');
    $pinterest->call(POST => '/v1/boards/', name => 'Awesome Pictures');
    $pinterest->call(PATCH => '/v1/boards/:board/', {board => 'awesome-pictures', description => $desc});

The parameters can be given as a hash or hashref, as in

    $pinterest->call($method => $path, %params);
    $pinterest->call($method => $path, \%params);

The module implements parameter validation, so errors are caught earlier and without the need to reach Pinterest servers (and consume your hourly quota).


I found that remembering the endpoints can be error-prone and boring. That is why the concept of "resources" as simple aliases to the endpoints has been incorporated to this module.

The examples given above with call() can be rewritten as:

    $pinterest->fetch('my/likes', fields => 'id,note,board,link,url,counts');
    $pinterest->create('board', name => 'Awesome Pictures');
    $pinterest->edit('board', {board => 'awesome-pictures', description => $desc});

Notice that resources are insensitive to singular/plural (for cases like 'my/likes' and 'my/like') and also insensitive to trailing slashes ('board/' works as well as 'board').

Based on the resources, there are also endpoint methods like:

    $pinterest->fetch_my_likes(fields => 'id,note,board,link,url,counts');
    $pinterest->create_board(name => 'Awesome Pictures');
    $pinterest->edit_board({board => 'awesome-pictures', description => $desc});


All supported endpoints are listed below. For details on the parameters for each call, take a look at
GET /v1/me/
    Resource: me

    Endpoint method: fetch_me
GET /v1/me/boards/
    Resource: my/boards me/boards

    Endpoint method: fetch_my_boards
GET /v1/me/boards/suggested/
    Resource: my/suggested/boards me/boards/suggested

    Endpoint method: fetch_my_suggested_boards
GET /v1/me/likes/
    Resource: my/likes me/likes

    Endpoint method: fetch_my_likes
GET /v1/me/pins/
    Resource: my/pins me/pins

    Endpoint method: fetch_my_pins
GET /v1/users/:user
    Resource: user

    Endpoint method: fetch_user
GET /v1/me/search/boards/
    Resource: search/my/boards me/search/boards

    Endpoint method: search_my_boards
GET /v1/me/search/pins/
    Resource: search/my/pins me/search/pins

    Endpoint method: search_my_pins
POST /v1/me/following/boards/
    Resource: my/following/board me/following/board

    Endpoint method: create_my_following_board
POST /v1/me/following/users/
    Resource: my/following/user me/following/user

    Endpoint method: create_my_following_user
GET /v1/me/followers/
    Resource: my/followers me/followers

    Endpoint method: fetch_my_followers
GET /v1/me/following/boards/
    Resource: my/following/boards me/following/boards

    Endpoint method: fetch_my_following_boards
GET /v1/me/following/interests/
    Resource: my/following/interests me/following/interests my/interests

    Endpoint method: fetch_my_following_interests
GET /v1/me/following/users/
    Resource: my/following/users me/following/users

    Endpoint method: fetch_my_following_users
DELETE /v1/me/following/boards/:board/
    Resource: my/following/board me/following/board

    Endpoint method: delete_my_following_board
DELETE /v1/me/following/users/:user/
    Resource: my/following/user me/following/user

    Endpoint method: delete_my_following_user
POST /v1/boards/
    Resource: board

    Endpoint method: create_board
GET /v1/boards/:board/
    Resource: board

    Endpoint method: fetch_board
GET /v1/boards/:board/pins/
    Resource: board/pins

    Endpoint method: fetch_board_pins
PATCH /v1/boards/:board/
    Resource: board

    Endpoint method: edit_board
DELETE /v1/boards/:board/
    Resource: board

    Endpoint method: delete_board
POST /v1/pins/
    Resource: pin

    Endpoint method: create_pin
GET /v1/pins/:pin/
    Resource: pin

    Endpoint method: fetch_pin
PATCH /v1/pins/:pin/
    Resource: pin

    Endpoint method: edit_pin
DELETE /v1/pins/:pin/
    Resource: pin

    Endpoint method: delete_pin


    $pinterest = WebService::Pinterest->new(%args);

Constructor. Accepts the arguments:

    access_token - most API calls require only this

    api_id - for authorization calls

    api_secret - needed for authorization_url()

    trace_calls - to enable tracing HTTP requests and responses to / from Pinterest
    $response = $pinterest->call($method, $endpoint, \%params);
    $response = $pinterest->call($method, $endpoint, \%params, \%opts);
    $response = $pinterest->call($method, $endpoint, %params);

For \%opts, {allow_extra => 1} can be used to tell the validation routine to allow extra parameters for the endpoint.

    $url = $pinterest->authorization_url(
        response_type => 'code',
        state         => $state,
        scope         => 'read_public,write_public',
        redirect_uri  => '',

Builds an authorization URL to request authorization from a user to read or change the Pinterest data in their account.


Requires app_id and app_secret attributes, besides response_type, scope, redirect_uri parameters.

state is optional but recommended, since this can be used to make sure that redirect back to your site or app wasn't spoofed.

scope is a comma-separated list of Pinterest permission scopes|

redirect_uri is the URI which the user will be redirected to after they authorize (or choose not to authorize) your app. This URI must be added to the list of redirect URIs in your Pinterest app configuration.

It is probably a good practice to keep track of the app user via the authorization state. If successful, Pinterest will generate a request to your app with the authorization state and an authorization code. The authorization code (which stands for temporary credentials) should then be exchanged by an access token (and may be obtained with a get_access_token() call. The access code in turn works as a permanent credential (until the user revokes app access).

    $response = $pinterest->get_access_token(
         grant_type => 'authorization_code',
         code       => $code,

Retrieves the access token corresponding to the authorization code obtained from an app user. This access token will then be used for the app to access Pinterest data on user's behalf.

Requires app_id and app_secret attributes, besides grant_type and code parameters.

    $method_endpoint = $pinterest->resolve_resource($method, $resource);

Returns an arrayref with the actual HTTP method and endpoint path for a Pinterest API call.

    $response = $pinterest->fetch($resource, %params);
    $response = $pinterest->fetch($resource, \%params);
    $response = $pinterest->fetch($resource, \%params, \%opts);

Resolves GET => $resource and, if successful, does a Pinterest API call to the resulting endpoint.

On failure, it croaks.

    $response = $pinterest->create($resource, %params);
    $response = $pinterest->create($resource, \%params);
    $response = $pinterest->create($resource, \%params, \%opts);

Resolves POST => $resource and, if successful, does a Pinterest API call to the resulting endpoint.

On failure, it croaks.

    $response = $pinterest->edit($resource, %params);
    $response = $pinterest->edit($resource, \%params);
    $response = $pinterest->edit($resource, \%params, \%opts);

Resolves PATCH => $resource and, if successful, does a Pinterest API call to the resulting endpoint.

On failure, it croaks.

    $response = $pinterest->delete($resource, %params);
    $response = $pinterest->delete($resource, \%params);
    $response = $pinterest->delete($resource, \%params, \%opts);

Resolves DELETE => $resource and, if successful, does a Pinterest API call to the resulting endpoint.

On failure, it croaks.

    $pager = $pinterest->fetch_paged($resource, %params);
    $pager = $pinterest->fetch_paged($resource, \%params);
    $pager = $pinterest->fetch_paged($resource, \%params, \%opts);

Resolves GET => $resource to a Pinterest API endpoint which supports paging. If successful, creates a pager object to iterate through the resulting response pages.

On failure, it croaks.



    $upload = $pinterest->upload($file_path);


    $pager = $pinterest->pager($method => $endpoint, %params);
    $pager = $pinterest->pager($method => $endpoint, \%params);
    $pager = $pinterest->pager($method => $endpoint, \%params, \%opts);

Used to implement fetch_paged(). See "PAGINATION".



By now, the parameters to the API calls are simply scalars. There is one exception for the endpoint

    POST /v1/pins/

It accepts an optional "image" parameter which should be an upload of the image content for the pin being created.

If you want to create a pin by uploading an image stored at a file in the local machine, use the methods upload() and create('pin', ...) as in the example below:

    $r = $pinterest->create('pin',
        board => 'nobody/hummingbirds',
        note  => 'Hummingbirds & Orchids',
        link  => '',
        image => $pinterest->upload($image_path),



Some "fetch" endpoints support pagination and each response contains a limited number of items in the list. The number of items per page can be specified by the "limit" parameter. This parameter defaults to 25 and can be at most 100.

You can traverse through the pages of a fetched result, using the fetch_paged() method which returns a "pager" object. The pager in turn is an iterator which returns one page at a time for each invocation of next() until no page is left, when a false value is returned.

The usage is illustrated below:

    $pager = $api->fetch_paged('board/pins', board => $board, limit => 50);
    while ($res = $pager->next) {



Please report bugs via Github


Adriano R. Ferreira, <>


Copyright (C) 2016 by Adriano R. Ferreira

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.