{"id":13448076,"url":"https://github.com/kijin/pinboard-api","last_synced_at":"2025-08-22T03:32:24.937Z","repository":{"id":2782990,"uuid":"3782575","full_name":"kijin/pinboard-api","owner":"kijin","description":"Pinboard API Client in PHP","archived":false,"fork":false,"pushed_at":"2016-11-11T07:47:24.000Z","size":36,"stargazers_count":100,"open_issues_count":2,"forks_count":13,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-08-12T12:40:48.434Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kijin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-03-21T02:20:46.000Z","updated_at":"2025-02-06T00:40:45.000Z","dependencies_parsed_at":"2022-09-10T01:10:49.381Z","dependency_job_id":null,"html_url":"https://github.com/kijin/pinboard-api","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/kijin/pinboard-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kijin%2Fpinboard-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kijin%2Fpinboard-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kijin%2Fpinboard-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kijin%2Fpinboard-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kijin","download_url":"https://codeload.github.com/kijin/pinboard-api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kijin%2Fpinboard-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271579433,"owners_count":24784250,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-22T02:00:08.480Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T05:01:34.860Z","updated_at":"2025-08-22T03:32:24.686Z","avatar_url":"https://github.com/kijin.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"\nPinboard API Client in PHP\n==========================\n\nThis library implements a client for the [Pinboard API](https://pinboard.in/api/).\nAll of the XML juggling is abstracted away, so that you can work with native PHP arrays and objects.\nCurrently, all features of API v1 are supported.\n\nThis library requires PHP 5 with the cURL extension. SSL support must be enabled.\nThis library also requires SimpleXML, which is enabled by default in most PHP 5 installations.\n\nThis library is released under the [MIT License](http://opensource.org/licenses/MIT).\nThe author and contributor(s) are not affiliated with Pinboard in any way except as customers.\n\n\n### Getting Started\n\nInstallation (without composer):\n\n    include 'pinboard-api.php';\n\nInstallation (with composer):\n\n    \"require\": {\n        \"kijin/pinboard-api\": \"dev-master\"\n    }\n\nBootstrap:\n\n    $pinboard = new PinboardAPI('username', 'password_or_token');\n\nCreate a new bookmark:\n\n    $bookmark = new PinboardBookmark;\n    $bookmark-\u003eurl = 'https://pinboard.in/';\n    $bookmark-\u003etitle = 'Pinboard';\n    $bookmark-\u003edescription = 'An awesome bookmarking service';\n    $bookmark-\u003etags = array('awesome', 'bookmarking');\n    $bookmark-\u003esave();\n    \nFind and edit an existing bookmark:\n\n    $bookmarks = $pinboard-\u003esearch_by_url('https://delicious.com/');\n    if (count($bookmarks)) {\n        $bookmark = $bookmark[0];\n        $bookmark-\u003edescription = 'Not so tasty anymore';\n        $bookmark-\u003etags[] = 'not-awesome'\n        $bookmark-\u003esave();\n    }\n\nDelete a bookmark:\n\n    $bookmark-\u003edelete();\n\nGet a list of your tags:\n\n    $tags = $pinboard-\u003eget_tags();\n    foreach ($tags as $tag) {\n        echo \"Tag '{$tag}' has {$tag-\u003ecount} bookmarks.\\n\";\n    }\n\n\nClasses and Methods\n===================\n\nThe Pinboard API Client is liberal in what it accepts but conservative in what it produces.\nTimestamps and tags are accepted in various formats,\nand a full `PinboardBookmark` object can often be replaced with just a URL.\nHowever, timestamps returned by the API Client will always be Unix timestamps\n(except in the case of `get_dates()` where you'll get dates in the `YYYY-MM-DD` format),\nand tags will always be strings in an array.\n\n\nPinboardAPI-\u003e__construct()\n--------------------------\n\nArguments:\n\n  - _required_ **$user** : your Pinboard username.\n  - _required_ **$pass** : your Pinboard password or API token.\n  - _optional_ **$connection_timeout** : connection timeout in seconds. Default is 10.\n  - _optional_ **$request_timeout** : request timeout in seconds. Default is 30.\n\nIf you want to use your API token instead of your account password,\nyou must use the full string as it appears in the \"settings\" page.\nThis includes your username, a colon character, and 20 uppercase hexademical digits.\n\nFor example:\n\n    $pinboard = new PinboardAPI('user', 'user:0123456789ABCDEFABCD');\n\nYou can also pass `null` instead of your username, since the token already includes your username.\nHowever, using any value other than your own username or `null` will result in authentication failure.\n\nPassword authentication will continue to work normally until Pinboard stops supporting it.\n\n\nPinboardAPI-\u003eenable_logging()\n-----------------------------\n\nUse this method if you would like to get notified every time the API Client makes a remote request.\nThis can be useful for debugging.\n\nArguments:\n\n  - _required_ **$func** : a callable that takes one argument.\n\nThe callable can be either a function name, a method name, or a closure.\nIt will be passed the remote URL whenever the API Client makes a request to Pinboard.\n\nThe following example will print `https://api.pinboard.in/v1/posts/update` to the console.\n\n    $pinboard = new PinboardAPI('username', 'password');\n    $pinboard-\u003eenable_logging(function($str) { echo \"$str\\n\"; });\n    $updated_time = $pinboard-\u003eget_updated_time();\n\nPinboardAPI-\u003eget_updated_time()\n-------------------------------\n\nUse this method to find out when you last made changes to your bookmarks.\nThis can help reduce unnecessary calls to expensive methods such as `get_all()`.\n\nAPI Method Call: `posts/update`\n\nArguments: none.\n\nReturns: integer (Unix timestamp).\n\n\nPinboardAPI-\u003eget_recent()\n-------------------------\n\nUse this method to grab your most recent bookmarks, optionally filtered by up to three tags.\nNote that Pinboard may impose rate limiting on this method.\n\nAPI Method Call: `posts/recent`\n\nArguments:\n\n  - _optional_ **$count** : integer, how many bookmarks to return. Default is 15. Maximum is 100.\n  - _optional_ **$tags** : an array of 1-3 tags, or a string with spaces between tags.\n\nReturns: an array of `PinboardBookmark` objects.\n\n\nPinboardAPI-\u003eget_all()\n----------------------\n\nUse this method to grab all of your bookmarks, optionally filtered by up to three tags or a time interval.\nNote that Pinboard may impose rate limiting on this method.\n\nIf you would like to skip any arguments, use `null` in place of the missing argument.\n\nAPI Method Call: `posts/all`\n\nArguments:\n\n  - _optional_ **$count** : integer, how many bookmarks to return. Default is all.\n  - _optional_ **$offset** : integer, when used with `$count`, how many bookmarks to skip.\n  - _optional_ **$tags** : an array of 1-3 tags, or a string with spaces between tags.\n  - _optional_ **$from** : a Unix timestamp, or any string that PHP can parse into a timestamp.\n  - _optional_ **$to** : a Unix timestamp, or any string that PHP can parse into a timestamp.\n\nReturns: an array of `PinboardBookmark` objects.\n\n\nPinboardAPI-\u003eget()\n------------------\n\nUse this method to grab some of your bookmarks, optionally filtered by up to three tags.\nPlease read Pinboard's [documentation](https://pinboard.in/api/#posts_get)\nfor details on how this method behaves when the date argument is absent.\n\nIf you would like to skip any arguments, use `null` in place of the missing argument.\n\nAPI Method Call: `posts/get`\n\nArguments:\n\n  - _optional_ **$url** : the exact URL of the bookmark to look for.\n  - _optional_ **$tags** : an array of 1-3 tags, or a string with spaces between tags.\n  - _optional_ **$date** : a Unix timestamp, any string that PHP can parse into a timestamp, or a date in the format `YYYY-MM-DD`.\n\nReturns: an array of `PinboardBookmark` objects.\n\n\nPinboardAPI-\u003esearch_by_url()\n----------------------------\n\nA shortcut to `get()`.\nNote that this method will return an array even if there is only one bookmark.\n\nArguments:\n\n  - _required_ **$url** : the exact URL of the bookmark to look for.\n\nReturns: an array of `PinboardBookmark` objects.\n\n\nPinboardAPI-\u003esearch_by_tag()\n----------------------------\n\nA shortcut to `get_all()`.\n\nArguments:\n\n  - _required_ **$tags** : an array of 1-3 tags, or a string with spaces between tags.\n\nReturns: an array of `PinboardBookmark` objects.\n\n\nPinboardAPI-\u003esearch_by_date()\n-----------------------------\n\nA shortcut to `get()`.\n\nArguments:\n\n  - _required_ **$date** : a Unix timestamp, any string that PHP can parse into a timestamp, or a date in the format `YYYY-MM-DD`.\n\nReturns: an array of `PinboardBookmark` objects.\n\n\nPinboardAPI-\u003esearch_by_interval()\n---------------------------------\n\nA shortcut to `get_all()`.\n\nArguments:\n\n  - _required_ **$from** : a Unix timestamp, or any string that PHP can parse into a timestamp.\n  - _required_ **$to** : a Unix timestamp, or any string that PHP can parse into a timestamp.\n\nReturns: an array of `PinboardBookmark` objects.\n\n\nPinboardAPI-\u003esave()\n-------------------\n\nUse this method to add a new bookmark or edit an existing bookmark.\n\nAPI Method Call: `posts/add`\n\nArguments:\n\n  - _required_ **$bookmark** : a `PinboardBookmark` object to save.\n  - _optional_ **$replace** : set to `false` if you don't want to overwrite an existing bookmark with the same URL. Default is `true`.\n\nReturns: `true` on success and `false` on failure. Call `get_last_status()` to read the error message in case of a failure.\n\nWhen not using `$replace`, it may be more intuitive to use `PinboardBookmark-\u003esave()` instead. See below for more information on using this alternative syntax.\n\n\nPinboardAPI-\u003edelete()\n---------------------\n\nUse this method to delete a bookmark.\n\nAPI Method Call: `posts/delete`\n\nArguments:\n\n  - _required_ **$bookmark** : a `PinboardBookmark` object, or a URL.\n\nReturns: `true` on success and `false` on failure. Call `get_last_status()` to read the error message in case of a failure.\n\nNote that it may be more intuitive to use `PinboardBookmark-\u003edelete()` instead. See below for more information on using this alternative syntax.\n\n\nPinboardAPI-\u003eget_dates()\n------------------------\n\nUse this method to get a list of dates on which you added bookmarks, with the number of bookmarks for each day.\nOptionally filtered by up to three tags.\n\nAPI Method Call: `posts/dates`\n\nArguments:\n\n  - _optional_ **$tags** : an array of 1-3 tags, or a string with spaces between tags.\n\nReturns: an array of `PinboardDate` objects. (These objects behave like strings.)\n\n\nPinboardAPI-\u003eget_suggested_tags()\n---------------------------------\n\nUse this method to get tag suggestions for a bookmark or URL.\n\nAPI Method Call: `posts/suggest`\n\nArguments:\n\n  - _required_ **$bookmark** : a `PinboardBookmark` object, or a URL.\n\nReturns: an associative array with two keys, `popular` and `recommended`, each of which contains an array of strings.\n\n\nPinboardAPI-\u003eget_tags()\n-----------------------\n\nUse this method to get a list of all your tags, with the number of bookmarks for each tag.\n\nAPI Method Call: `tags/get`\n\nArguments: none.\n\nReturns: an array of `PinboardTag` objects. (These objects behave like strings.)\n\n\nPinboardAPI-\u003erename_tag()\n-------------------------\n\nUse this method to rename one tag to another.\n\nAPI Method Call: `tags/rename`\n\nArguments:\n\n  - _required_ **$old** : the old name, as a string.\n  - _required_ **$new** : the new name, as a string.\n\nReturns: `true` on success and `false` on failure. Call `get_last_status()` to read the error message in case of a failure.\n\n\nPinboardAPI-\u003edelete_tag()\n-------------------------\n\nUse this method to delete a tag. Bookmarks will not be deleted.\n\nAPI Method Call: `tags/delete`\n\nArguments:\n\n  - _required_ **$tag** : the tag to delete, as a string.\n\nReturns: `true` on success and `false` on failure. Call `get_last_status()` to read the error message in case of a failure.\n\n\nPinbiardAPI-\u003elist_notes()\n-------------------------\n\nUse this method to list your notes.\n\nAPI Method Call: `notes/list`\n\nArguments: none.\n\nReturns: an array of `PinboardNote` objects.\n\nAs of August 2014, this API call only returns metadata.\nIn order to get the content of each note, please use `get_note()`.\n\n\nPinboardAPI-\u003eget_note()\n-----------------------\n\nUse this method to get the contents of a single note.\n\nAPI Method Call: `notes/ID`\n\nArguments:\n\n  - _required_ **$id** : the ID of the note that you want to get.\n\nReturns: a `PinboardNote` object, or `false` if the note does not exist.\n\nAs of August 2014, this API call returns the title, content, and minimal metadata.\nIn order to get the rest of the metadata, please use `list_notes()`.\n\n\nPinboardAPI-\u003eget_rss_token()\n----------------------------\n\nUse this method to get your secret RSS token.\n\nAPI Method Call: `user/secret`\n\nArguments: none.\n\nReturns: a string containing your RSS token.\n\n\nPinboardAPI-\u003eget_api_token()\n----------------------------\n\nUse this method to get your API token.\n\nAPI Method Call: `user/api_token`\n\nArguments: none.\n\nReturns: a string containing your API token.\n\nNote that this method only returns the hexademical part of the API token.\nIn order to use the token for authentication, you must combine it with the username.\nSee the documentation for `__construct()` for more information on how to use the token for authentication.\n\n\nPinboardAPI-\u003eget_last_status()\n------------------------------\n\nUse this method to retrieve any error message for one of the following methods: `save()`, `delete()`, `rename_tag()`, and `delete_tag()`.\nIf the last operation did not fail, this method will return \"done\".\nIf no applicable operation has been performed, this method will return `null`.\n\nArguments: none.\n\nReturns: a string containing the last error message, or `null`.\n\n\nPinboardAPI-\u003edump()\n-------------------\n\nUse this method to back up all of your bookmarks.\nThe dump will be produced in an XML format that can be easily imported into Pinboard, Delicious,\nor any other online bookmarking service that supports importing bookmarks in the Delicious format.\nNote that Pinboard may impose rate limiting on this method.\n\nAPI Method Call: `posts/all`\n\nArguments: none.\n\nReturns: a string containing the XML dump.\n\n\nThe PinboardBookmark class\n--------------------------\n\nThis class is used with `save()` and several other methods that take bookmarks as an argument.\nIts use is required when calling `save()`, but in most other cases it can be substituted with just a URL.\nThe API Client will also return instances of this class whenever it fetches bookmarks from Pinboard.\n\nThe following properties can be adjusted freely:\n\n  - _required_ **url** : the URL of the bookmark.\n  - _required_ **title** : the title of the bookmark.\n  - _optional_ **description** : any additional description.\n  - _optional_ **timestamp** : a Unix timestamp, or any string that PHP can parse into a timestamp.\n  - _optional_ **tags** : an array of 1-3 tags, or a string with spaces between tags.\n  - _optional_ **is_public** : `true` or `false`. Default is determined by your Pinboard account settings.\n  - _optional_ **is_unread** : `true` or `false`. Default is `false`.\n\nThe following properties are also public, but they will not be saved when you call `save()`:\n\n  - **hash** : an MD5 hash of the URL that Pinboard uses to uniquely identify bookmarks.\n  - **meta** : another hash that can be used to detect when a bookmark is changed.\n  - **others** : the number of other Pinboard users who have bookmarked the same URL.\n\nThe following methods are available:\n\n  - **save()** : save this bookmark.\n  - **delete()** : delete this bookmark.\n\nYou can use these methods instead of `PinboardAPI-\u003esave($bookmark)` and `PinboardAPI-\u003edelete($bookmark)` to save or delete individual bookmarks.\nThis may be more intuitive to developers who are used to common ORM idioms, which this library tries to mimic.\n\nFor example, instead of:\n\n    $pinboard-\u003esave($bookmark);\n\nYou can simply do:\n\n    $bookmark-\u003esave();\n\nIf only one instance of `PinboardAPI` exists in the current script (which will usually be the case),\nthe API Client automatically uses it to save or delete all bookmarks, even newly created ones.\nSo there is no need for `PinboardBookmark` instances to interact explicitly with `PinboardAPI` instances.\n\nHowever, if you create multiple instances of `PinboardAPI` using different login credentials\n(perhaps because you want to copy or move bookmarks from one Pinboard account to another),\nthese methods will throw `PinboardException` because they don't know which instance to use.\nIn that case, you should use the equivalent methods on `PinboardAPI` instances instead,\nor pass the appropriate `PinboardAPI` instance as an argument to `save()` and `delete()`.\nBoth methods take one optional argument, which should be a `PinboardAPI` instance.\n\nThe following example copies bookmarks from one Pinboard account to another:\n\n    $pinboard1 = new PinboardAPI('user1', 'pass1');\n    $pinboard2 = new PinboardAPI('user2', 'pass2');\n    $bookmarks = $pinboard1-\u003esearch_by_tag('tag');\n    foreach ($bookmarks as $bookmark) {\n        $bookmark-\u003esave($pinboard2);  // Equivalent to $pinboard2-\u003esave($bookmark);\n        sleep(3);  // Comply with Pinboard's rate limiting policy\n    }\n\nEven when using multiple instances, bookmarks that were retrieved using one of the `get_*` or `search_*` methods\nwill remember which instance they came from, and therefore `save()` and `delete()` will work without any problem,\nas shown in the following example:\n\n    $pinboard1 = new PinboardAPI('user1', 'pass1');\n    $pinboard2 = new PinboardAPI('user2', 'pass2');\n    $bookmarks = $pinboard1-\u003esearch_by_url('http://awesome-website.com/');\n    $bookmark = $bookmarks[0];\n    $bookmark-\u003edescription = 'New description';\n    $bookmark-\u003esave();  // Automatically saved to $pinboard1\n\n\nThe PinboardDate class\n----------------------\n\nInstances of this class are returned by `get_dates()`. They contain dates in the format `YYYY-MM-DD`.\nFor all intents and purposes, these objects can be used exactly like strings.\nThe only difference is that it has a `count` property, which contains the number of bookmarks added on the corresponding date.\n\nExamples:\n\n    echo $date;         // prints '2012-03-20'\n    echo $date-\u003edate;   // prints '2012-03-20'\n    echo $date-\u003ecount;  // prints '16'\n\n\nThe PinboardTag class\n---------------------\n\nInstances of this class are returned by `get_tags()`.\nFor all intents and purposes, these objects can be used exactly like strings.\nThe only difference is that it has a `count` property, which contains the number of bookmarks added on the corresponding date.\n\nIn order to conserve resources, this class is **not** used in other contexts,\nsuch as the `tags` property of `PinboardBookmark` objects, the output of `get_suggested_tags()`,\nor any other situation where the count is not relevant.\n\nExamples:\n\n    echo $tag;         // prints 'awesome'\n    echo $tag-\u003etag;    // prints 'awesome'\n    echo $tag-\u003ecount;  // prints '42'\n\n\nThe PinboardNote class\n---------------------\n\nInstances of this class are returned by `list_notes()` and `get_note()`.\nCurrently, it is not possible to save a note to Pinboard through the API.\n\nBecause different API calls return a different subset of content and metadata, not all of the following properties may be populated.\nThe only property that is guaranteed to be populated is `id`. Unpopulated properties will have the value of `null`.\nSee documentation for the methods above for more details.\n\nThe following properties are available:\n\n  - **id**\n  - **title**\n  - **hash**\n  - **created_at**\n  - **updated_at**\n  - **length**\n  - **text**\n\n\nError Handling\n--------------\n\nThe Pinboard API Client defines the following exceptions:\n\n  - `PinboardException` (extends `Exception`) is thrown in all error situations not covered by the other exceptions,\n    such as attempting to save a bookmark with an invalid URL or an empty title.\n  - `PinboardException_ConnectionError` (extends `PinboardException`) is thrown if the library encounters problems\n    while connecting to Pinboard's servers. This is most likely due to some sort of outage.\n  - `PinboardException_AuthenticationFailure` (extends `PinboardException`) is thrown in case of authentication failure.\n    This may be because the username and password/token do not match, or because you supplied the API token in the wrong format.\n    (The API token must include the username, not just the hexademical portion.)\n  - `PinboardException_TooManyRequests` (extends `PinboardException`) is thrown if the server responds with HTTP code 429, \"Too Many Requests\".\n    This means that you should slow down and wait a few minutes before making additional calls to `get()` or `get_all()`.\n    See [here](https://pinboard.in/tos/) and [here](https://pinboard.in/api/#limits) for more information on rate limiting.\n  - `PinboardException_InvalidResponse` (extends `PinboardException`) is thrown if the server responds\n    with any HTTP code other than 200 and 429, or if it returns invalid XML.\n\nNote that some methods will return `false` instead of throwing an exception on failure.\nThis is because the author has judged that errors in those cases are not \"exceptional\".\n(For example, it is harmless to try to delete a bookmark that has already been deleted.)\nAll such cases are clearly documented above.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkijin%2Fpinboard-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkijin%2Fpinboard-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkijin%2Fpinboard-api/lists"}