{"id":20277337,"url":"https://github.com/bitjson/couple-api","last_synced_at":"2025-04-11T05:50:41.555Z","repository":{"id":29367559,"uuid":"32902218","full_name":"bitjson/couple-api","owner":"bitjson","description":"Unofficial Couple CLI and node library (incomplete)","archived":false,"fork":false,"pushed_at":"2016-11-11T16:56:58.000Z","size":43,"stargazers_count":10,"open_issues_count":18,"forks_count":4,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-10-22T16:18:54.688Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bitjson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-26T02:05:51.000Z","updated_at":"2022-01-31T10:38:00.000Z","dependencies_parsed_at":"2022-08-29T14:11:40.653Z","dependency_job_id":null,"html_url":"https://github.com/bitjson/couple-api","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitjson%2Fcouple-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitjson%2Fcouple-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitjson%2Fcouple-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitjson%2Fcouple-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitjson","download_url":"https://codeload.github.com/bitjson/couple-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248351425,"owners_count":21089271,"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","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-11-14T13:18:00.036Z","updated_at":"2025-04-11T05:50:41.530Z","avatar_url":"https://github.com/bitjson.png","language":"JavaScript","readme":"[![npm version](https://img.shields.io/npm/v/couple-api.svg)](https://www.npmjs.com/package/couple-api) [![Build Status](https://img.shields.io/travis/bitjson/couple-api.svg)](https://travis-ci.org/bitjson/couple-api) [![Coverage Status](https://img.shields.io/coveralls/bitjson/couple-api.svg)](https://coveralls.io/r/bitjson/couple-api) [![Dependency Status](https://img.shields.io/david/bitjson/couple-api.svg)](https://david-dm.org/bitjson/couple-api)\n\n# Couple API\nAn unofficial Node client and command-line interface for the [Couple App](https://couple.me/) API.\n\nAn excellent [web client](https://app.couple.me/) is available for Couple, but it seems to be using a somewhat outdated version of Couple's internal API (\"Juliet\" Version: `1.40`). For stability and access to the latest features, this library is built around the API methods used by the Couple iOS app (\"Juliet\" Version: `1.70`).\n\n**WIP** : Please note, methods marked \"WIP\" are not yet implemented.\n\nThis library is currently only intended for interaction with the Couple timeline, and does not include methods for interacting with `Lists`, `Settings`, or the `Calendar`. Please feel free to [open an issue](https://github.com/bitjson/couple-api/issues), if you'd like to see it expanded!\n\n## Node Client\nBefore interacting with the Couple API, you'll need to authenticate your client instance.\n\n### Authenticate\nThe `authenticate` method retrieves your Couple App `authObject` using your username and password.\n\nThe `authObject` contains both your user profile and the profile of your `other`. It also contains your `authToken`, which is needed to authenticate other API calls. The `authToken` seems to expire at least monthly, as well as when the user's password is changed.\n\n```js\nvar couple = new Couple();\nvar email = 'email@example.com';\nvar password = 'hunter2';\ncouple.authenticate(email, password, function(err, resObj) {\n  if(err) return console.error(err);\n  console.log('Client `couple` is authenticated:');\n  console.log(couple.identify());\n});\n```\n\n### WIP: Timeline\nAll events – messages, stickers, nudges (`Thinking of you...`), etc. – are recorded in the `Timeline`. Upon logging in, the mobile apps begin downloading the timeline, 1600 events at a time, fetching and downloading media as it's encountered.\n\nThe `Timeline` function accepts an options object and a callback, and returns a `Timeline` object. The `Timeline` object includes all the information returned by the Couple API, as well as some convenience properties to make consecutive calls easier.\n\n```js\nvar options = {\n  // using defaults:\n  // limit: 1600,\n  // order: desc,\n  // after: ''\n};\n\ncouple.timeline(options, function(err, timeline) {\n  if(err) return console.error(err);\n  console.log(timeline);\n});\n```\n\n#### Moments\nNote, the web app (API version `1.40`) has a `/moments` endpoint (not currently implemented in this library), but the mobile apps rely on caching the timeline to generate the `Moments` section.\n\n### WIP: Sending\n[Coming soon...]\n\n## Client API\n\n```js\nvar couple = require('couple-api');\n```\n\nAll library methods are documented below. This library strives for 100% test coverage, so examples of all implemented functionality and sample Couple API responses can be found in the [`test`](/test) directory.\n\n### Authenticate\n\n```js\ncouple.authenticate(email, password, callback);\n```\n\nAuthenticates the `couple-api` instance. The method fetches the users `AuthObject` which contains a variety of information and is needed to authenticate all other calls.\n\n#### Params\n\nName       | Description\n---------- | -------------------------\n`email`    | The user's email address.\n`password` | The user's password.\n\n#### callback(err, responseObject)\nCalled when the Couple API returns a response. All other methods can be called on the Couple instance after this callback is called. See tests for more detail.\n\n### Identify\n\n```js\ncouple.identify();\n```\n\nReturns an `identify` object.\n\nName        | Description\n----------- | -------------------------------------------------------------------------------------\n`userID`    | The ID (email address) of the authenticated user.\n`authToken` | The user's base64 encoded authentication token.\n`otherID`   | The ID (email address) of the other user paired with the authenticated user.\n`apiHost`   | The full URL for Couple API server assigned to the user (to which requests are made).\n`userUuid`  | A unique version 4 UUID assigned to the user by Couple.\n`pairUuid`  | A unique version 4 UUID assigned to the pair by Couple.\n\n### WIP: Timeline\n\n```js\ncouple.timeline(options, callback);\n```\n\nReturns a segment of the authenticated user's Couple timeline.\n\n#### Options\n\nName    | Description\n------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n`limit` | The number of events to return. It seems that Couple has not yet implemented a maximum `limit`, but it's probably best to rely on pagination in your app, rather than downloading the whole timeline at once. If not set, this property will use the default value used by the mobile apps, `1600`.\n`order` | Chronological order of results. Options: `desc` or `asc`. Defaults to `desc`.\n`after` | Sets the starting point of the timeline segment retrieved. Accepts the `itemID` of the event occurring immediately before the first event in the response. By default, this is an empty string: `''`, causing the response to begin before the `pair` event, the first event in the whole timeline.\n\n#### Callback(err, timeline)\nCalled when the Couple API returns a response.\n\n##### timeline\nThe `timeline` object contains the `events` returned by the Couple API and additional properties.\n\n```js\n// timeline:\n{\n  'firstItemID': 'timeStampxxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',\n  'lastItemID': 'timeStampxxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',\n  'events': [\n    {\n      // event object\n    },\n    {\n      // event object\n    },\n    ...\n  ]\n}\n```\n\n##### events\nEvery entry in the Couple `timeline` is an `event`. The Couple timeline contains several types of events. All events have a number of similar properties.\n\nProperty    | Value\n----------- | ----------------------------------------------------------------------------------------------------------------------------------\n`cver`      | Couple app version which created the event. Prefix `i` for iOS (eg. `i1.9.9`), `a` for android, and `w` for the web client.\n`eventType` | The event type.\n`from`      | The email of the user who created the event.\n`itemID`    | A unique identifier – the event's timestamp, concatenated with a version 4 UUID. (`timeStampxxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`)\n`lID`       | A unique 9 character, numerical ID – seems to be used internally by the mobile apps.\n`pairingID` | A unique version 4 UUID assigned to the pair by Couple.\n`timeStamp` | The timestamp of the event in milliseconds.\n\nEach `eventType` also has a number of unique properties.\n\n###### text\nThe text event is a normal message.\n\nProperty      | Value\n------------- | ------------------------------------------------------------------------------------------------------------------------------------\n`eventType`   | Set to `text`.\n`enc`         | Text encoding. Only set on `text` events sent from the iOS app, which base64 encodes the `text` field. When set, the value is `b64`.\n`text`        | The contents of the message. May be base64 encoded.\n`decodedText` | Property added to all `text` events by `couple-api`. Always contains the contents of the message.\n\n###### pair\nThe pair event is the first event in the timeline.\n\nProperty    | Value\n----------- | ---------------------------------\n`eventType` | Set to `pair`.\n`pairType`  | Seems to always be set to `pair`.\n\nThe `pair` event does not contain the `cver`, `from`, or `lID` properties.\n\n###### sticker\nThe sticker event displays a sticker from a Couple sticker pack.\n\n```js\n  {\n    \"cver\": \"i1.9.9\",\n    \"eventType\": \"sticker\",\n    \"from\": \"user@example.com\",\n    \"itemID\": \"timeStampxxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\",\n    \"lID\": \"#########\",\n    \"pack\": 19,\n    \"pairingID\": \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\",\n    \"sticker\": 3,\n    \"timeStamp\": 1430522000000\n  }\n```\n\n###### nudge\n\n```js\n  {\n    \"cver\": \"i1.9.9\",\n    \"eventType\": \"nudge\",\n    \"from\": \"user@example.com\",\n    \"itemID\": \"timeStampxxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\",\n    \"lID\": \"#########\",\n    \"pairingID\": \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\",\n    \"timeStamp\": 1430522000000\n  }\n```\n\n# WIP: CLI\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitjson%2Fcouple-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitjson%2Fcouple-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitjson%2Fcouple-api/lists"}